Tuesday, December 16, 2014

Java8

Lambda's and Functional Interfaces

Java 8 is a major improvement and has rich set of features since Java5 . Main draw back with java language was it lacked functional style of programming . Java8 Fixed  this , following set of examples to lambda's and other features  introduced in java8 . 

Lambda expressions are basically anonymous methods , Java can now do functional composition in addition to object composition . 

Example of Imperative style 

public static void printArray(List arrtoprint)
    {
        for( int i =0; i< arrtoprint.size(); i++)
        {
            System.out.println(arrtoprint.get(i));
        }
    }

    public static void printArrayJava5(List arrtoprint)
    {
        for( String s:arrtoprint)
        {
            System.out.println(s);
        }
    }

both use external iterators , and boundary conditions , algorithm of looping are all controlled by the code. 

Example of Declarative ( functional) Style 

Implementation uses internal iterators

 public static void printArrayJava8(List arrtoprint)
    {
       arrtoprint.forEach(System.out::println);
    }
lot of things inferred in the above implementation

Descriptive syntax to show print element for each string element in arraylist

  arrtoprint.forEach((String e)->System.out.println(e));

Can be shortened to this format , print the element in the arraylist
 arrtoprint.forEach(System.out.println(e));

Can be further shortened to this .There is only one element to print , so not even have to mention that 
arrtoprint.forEach(System.out::println);

Why this is better 

Declarative style , values go through  mutation - constantly changed
Imperative Style , No mutation - can be parallelized easily 
Remove the mechanics - e.g looping can be sequential , or be concurrent or lazy 
Implementation done through java interface Consumer 

values.forEach( new Consumer() {

public accept(Interger value)
{
     System.out.println(value);
}
});

Example with return 

Functional style can also be used with methods that have a return , example for sorting the implementation would be 

  arrtosort.sort((e1,e2)-> e1.compareTo(e2));

return  is not required when there is only one variable to be returned . Descriptive syntax for this would be

arrtosort..sort( ( e1, e2 ) -> {
    int result = e1.compareTo( e2 );
    return result;
} );

Example using stream

Java 8 provides a new API (called Streams) that supports many parallel operations to process data and resembles the way you might think in database query languages—you express what you want in a higher-level manner, and the implementation (here the Streams library) chooses the best low-level execution mechanism. As a result, it avoids the need for you to write code that uses synchronized, which is not only highly error prone but is also more expensive than you may realize on multicore CPUs.Here is an example to filter out only even numbers from a arraylist of integers and print them

 public static void printEvenFunctional(List intArr)
    {
       intArr.stream().filter(e->e%2!=0).forEach(System.out::println); 
    }

This makes use of the Predicate interface java.util.function.Predicate . 

Descriptive syntax would be 
   public static void printEvenFunctionalDescriptive(List intArr)
    {

        intArr.stream().filter(
                new CheckInt()
        ).forEach(System.out::println); ;
    }

CheckInt class would be 


class CheckInt implements Predicate
{
    public boolean test(Integer i)
    {
         return i%2==0 ;
    }
}
Stream api allows code to be written  that is 
  • Declarative— More concise and readable
  • Composable— Greater flexibility
  • Parallelizable— Better performance

parallelStream

above example uses sequential stream , it can be changed to parallelStream by just changing

intArr.stream()
to
intArr.parallelStream()

Optional 

Java8 introduces new class java.util.Optional . Its the idea inspired from Scala and Haskell and it attempts to solve the problem 

public class Person{

Optional phone ;
 public Optional getCellphone()
 {
       return phone;
 }

}

ifPresent / orElse 

price = phone.orElse( defaultPhone ).getPrice();


phone.ifPresent( p -> System.out.println("Phone is present for person") );

can also be applied on streams as shown below

employee.stream()
        .filter(Employee::isRelocated)
        .findAny()
        .ifPresent( e -> System.out.println(e.getName() );

No comments: