Wednesday, March 29, 2017

New Features of Java 8

1) Interface changes:
Java 8 interface changes include static methods and default methods in interfaces. Prior to Java 8, we could have only method declarations in the interfaces. But from Java 8, we can have default methods and static method implementaions
Default Method: 
For creating a default method in java interface, we need to use “default” keyword with the method signature
public interface Interface1 {
void method1(String str);
default void log(String str){
 System.out.println("I1 logging::"+str);
}
}

Notice that log(String str) is the default method in the Interface1. Now when a class will implement Interface1, it is not mandatory to provide implementation for default methods of interface. This feature will help us in extending interfaces with additional methods, all we need is to provide a default implementation.

Java interface default methods will help us in removing base implementation classes, we can provide default implementation and the implementation classes can chose which one to override.
Java interface default methods will help us in extending interfaces without having the fear of breaking implementation classes.

                                     Java Interface Static Method
Java interface static method is similar to default method except that we can’t override them in the implementation classes. This feature helps us in avoiding undesired results in case of poor implementation in implementation classes.
Java interface static method is part of interface, we can’t use it for implementation class objects.
Java interface static methods are good for providing utility methods,for example null check, collection sorting etc.
Java interface static method helps us in providing security by not allowing implementation classes to override them.
We can’t define interface static method for Object class methods, we will get compiler error as “This static method cannot hide the instance method from Object”. This is because it’s not allowed in java, since Object is the base class for all the classes and we can’t have one class level static method and another instance method with same signature.

2.Java Functional Interfaces

An interface with exactly one abstract method is known as Functional Interface.
       A new annotation @FunctionalInterface has been introduced to mark an interface as Functional Interface. @FunctionalInterface annotation is a facility to avoid accidental addition of abstract methods in the functional interfaces. It’s optional but good practice to use it.
Static methods, by definition, are not abstract – @FunctionalInterface can have zero or more static methods

        Ex- 1 Interface Predicate<T>
       Type Parameters:T - the type of the input to the predicate
This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference. It has a abstract method test(T t ) and other methods
      
boolean test(T t) Evaluates this predicate on the given argument.
       Parameters: t - the input argument
       Returns:true if the input argument matches the predicate,     otherwise false
       Ex 2: Interface Runnable
This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.

3.Lamda Expressions
One of the major benefits of functional interface is the possibility to use lambda expressions to instantiate them. We can instantiate an interface with anonymous class but the code looks bulky.
Runnable r = new Runnable(){
@Override public void run() {
System.out.println("My Runnable");
 }
};
Since functional interfaces have only one method, lambda expressions can easily provide the method implementation. We just need to provide method arguments and business logic. For example, we can write above implementation using lambda expression as:
Runnable r1 = () -> { System.out.println("My Runnable"); };
 lambda expressions are means to create anonymous classes of functional interfaces easily. There are no runtime benefits of using lambda expressions

4. Java Time API
It has always been hard to work with Date, Time and Time Zones in java. There was no standard approach or API in java for date and time in Java. One of the nice addition in Java 8 is the java.time package that will streamline the process of working with time in java.
Just by looking at Java Time API packages. It has some sub-packages java.time.format that provides classes to print and parse dates and times and java.time.zone provides support for time-zones and their rules.

5.forEach() method in Iterable interface
Whenever we need to traverse through a Collection, we need to create an Iterator whose whole purpose is to iterate over and then we have business logic in a loop for each of the elements in the Collection. We might get ConcurrentModificationException if iterator is not used properly.
Java 8 has introduced forEach method in java.lang.Iterable interface so that while writing code we focus on business logic only. forEach method takes java.util.function.Consumer object as argument, so it helps in having our business logic at a separate location that we can reuse. Let’s see forEach usage with simple example.

Ex -public static void main(String[] args) {
//creating sample Collection List<Integer> myList = new ArrayList<Integer>();
     for(int i=0; i<10; i++)
       myList.add(i);
//traversing using Iterator
Iterator<Integer> it = myList.iterator();
while(it.hasNext()){
Integer i = it.next();
 System.out.println("Iterator Value::"+i);
       }
//traversing through forEach method of Iterable with anonymous class
myList.forEach(new Consumer<Integer>()
{
public void accept(Integer t) {
System.out.println("forEach anonymous class Value::"+t);
 }
 });
//traversing with Consumer interface implementation MyConsumer action = new MyConsumer(); myList.forEach(action);
 

//Consumer implementation that can be reused
class MyConsumer implements Consumer<Integer>{
public void accept(Integer t) {
System.out.println("Consumer impl Value::"+t);
 }
 }
The number of lines might increase but forEach method helps in having the logic for iteration and business logic at separate place resulting in higher separation of concern and cleaner code.

6.Concurrency API improvements
Some important concurrent API enhancements are
ConcurrentHashMap compute(), forEach(), forEachEntry(), forEachKey(), forEachValue(), merge(), reduce() and search() methods.
CompletableFuture that may be explicitly completed (setting its value and status).
Executors newWorkStealingPool() method to create a work-stealing thread pool using all available processors as its target parallelism level.
7.Nashorn Java Script Engine
Nashorn engine  lets you integrate Java with JavaScript on a highly performant virtual machine. It is also incredibly compliant with the ECMAScript standard for JavaScript
You can run JavaScript through the jjs interpreter, or from Java via the scripting API.
Use the predefined JavaScript objects for the most common packages, or the Java.type function to access any package.
Beware of intricacies in the conversion of strings and numbers between JavaScript and Java.
JavaScript offers a convenient syntax for working with Java lists and maps, as well as JavaBeans properties.
You can convert JavaScript functions to Java interfaces in a way that is very similar to using lambda expressions.
You can extend Java classes and implement Java interfaces in JavaScript, but there are limitations.
Nashorn has good support for writing shell scripts in JavaScript.
You can write JavaFX programs in JavaScript, but the integration is not as good as it might be

Running Java script from Java command line tool
To start run tool jjs ,make sure java path is set
> jjs
        jjs> 'Hello, World' Hello, World
You can define functions and call them
jjs> function factorial(n) { return n <= 1 ? 1 : n * factorial(n - 1) }
        function factorial(n) { return n <= 1 ? 1 : n * factorial(n - 1) }
         jjs> factorial(10) 3628800

Running Nashorn from Java
To run a script, you need to get a ScriptEngine object. If the engine is registered, you can simply get it by name. Java 8 includes an engine with name "nashorn".
Here is how to use it:
public class Test {
   public static void main(String[] args) throws ScriptException {
      ScriptEngineManager manager = new ScriptEngineManager();
      ScriptEngine engine = manager.getEngineByName("nashorn");
      Object result = engine.eval("'Hello, World!'.length");
       System.out.println(result);
  }
}

8.Collection Improvements:
Class/Interface
l

8.1 How to use removeIf method

The removeIf() method is used to remove all of the elements of this collection that satisfy the given predicate. Errors or runtime exceptions are thrown during iteration or by the predicate are relayed to the caller.
Ex:   class SamplePredicate<t> implements Predicate<t>{  
  T varc1;  
  public boolean test(T varc){  
  if(varc1.equals(varc)){  
      return true;  
  }  
  return false;  
}  
}  

public class test {  
  public static void main(String[] args) {  
   ArrayList<Stringcolor_list;  
  SamplePredicate<String> filter;  
  color_list = new ArrayList<> ();  
  filter = new SamplePredicate<> ();  
    
   filter.varc1 = "White";  
    color_list.add("White");  
    color_list.add("Black");  
    color_list.add("Red");  
    color_list.add("White");  
    color_list.add("Yellow");  
    color_list.add("White");  
    
  System.out.println("List of Colors");  
  System.out.println(color_list);  
    
  // Remove all White colors from color_list  
  color_list.removeIf(filter);      
  System.out.println("Color list, after removing White colors :");  
  System.out.println(color_list);  
    } 
 } 
Output: Color list, after removing White colors : [Black, Red, Yellow]

8.2 How to use replaceAll method of list
replaceAll(UnaryOperator<E> operator)
The replaceAll() method is used to replace each element of this list with the result of applying the operator to that element. Errors or runtime exceptions are thrown by the ope
rator are relayed to the caller.
Ex-class MyOperator<T> implements UnaryOperator<T>{  
           T varc1;  
 public T apply(T varc){  
  return varc1;  
 }  
        }  

public class Test
  public static void main(String[] args) { 
  
  ArrayList<String> color_list
  MyOperator<String> operator; 
   
  color_list = new ArrayList<> (); 
  operator = new MyOperator<> (); 
   
    operator.varc1 = "White"; 
    color_list.add("White"); 
    color_list.add("Black"); 
    color_list.add("Red"); 
    color_list.add("White"); 
    color_list.add("Yellow"); 
    color_list.add("White"); 
   
    System.out.println("List of Colors"); 
    System.out.println(color_list); 
   
 // Replace all colors with White color  
    color_list.replaceAll(operator); 
    System.out.println("Color list, after replacing all colors with White color :"); 
    System.out.println(color_list);     
  
}
Output:
List of Colors [White, Black, Red, White, Yellow, White]
Color list, after replacing all colors with White color : [White, White, White, White, White, White]

8.3 Spliterator
An object for traversing and partitioning elements of a source. The source of elements covered by a Spliterator could be, for example, an array, a Collection, an IO channel, or a generator function.A Spliterator may traverse elements individually (tryAdvance()) or sequentially in bulk (forEachRemaining()).
Methods:
int characteristics():Returns a set of characteristics of this Spliterator and its elements.
Returns an estimate of the number of elements that would be encountered by a forEachRemaining(java.util.function.Consumer<? super T>) traversal, or returns Long.MAX_VALUE if infinite, unknown, or too expensive to compute
boolean tryAdvance(Consumer<? super T> action) :
If a remaining element exists, performs the given action on it, returning true; else returns false.
boolean trySplit() :If this spliterator can be partitioned, returns a Spliterator covering elements, that will, upon return from this method, not be covered by this Spliterator.

8.4 forEachRemaining method
This method is found in Iterator and Spliterator  both interfaces
For Iterator : default void forEachRemaining(Consumer<? super E> action)
It Performs the given action for each remaining element until all elements have been processed or the action throws an exception. Actions are performed in the order of iteration, if that order is specified. Exceptions thrown by the action are relayed to the caller.
Implementation Requirements: The default implementation behaves as if:
          while (hasNext())
          action.accept(next());
For Spliterator : default void forEachRemaining(Consumer<? super T> action)
Implementation Requirements: The default implementation repeatedly invokes tryAdvance(java.util.function.Consumer<? super T>) until it returns false. It should be overridden whenever possible.
Performs the given action for each remaining element, sequentially in the current thread, until all elements have been processed or the action throws an exception. If this Spliterator is ORDERED, actions are performed in encounter order. Exceptions thrown by the action are relayed to the caller.