Sunday, March 18, 2018

Java 8 Features with Examples

java 8 features with examples-programinjava

Java 8 was a huge release from this development platform. The Java programming model went through a major upgrade with this release along with an evolution of the libraries and JVM. 
There was a significant increase in the overall ease of use, performance and productivity. Java 8.0 was officially released in 2014.
Also see : Java 9 Features with Examples




What makes Java 8 different from Java 7?

  • Java 7 was the first major update under Oracle for the Java Programming language while Java 8 was one of the biggest.
  • JVM’s support for dynamically-typed language was one of the major features of Java 7. It also added a language support for String in the switch statement. This has enabled users to rewrite programs efficiently and the code also becomes more readable. 
  • One catch block can catch multiple exception types with JDK 7 which led to better exception handling. The class-loader architecture was also enhanced as part of this update.
  • The most anticipated update of Java 8 was the introduction of lambda expressions which enable the coder to add local functions as arguments to methods.
  • The Other most important update of Java 8 is the Adding the Capability of Functional Programming in java 
  • The Date and Time API also got a new API in Java 8. Also, Nashorn, a JavaScript engine was introduced to run scripts on JVM.


Java 8 Features and Examples 

1) Support for lambda exression in APIs 
This is the most anticipated feature of the update. The introduction of Lambda Expressions allows us to write functional style code.

The Java Lambda syntax is:
(Argument-list) -> {body} 
Here the argument list can be null or empty. The arrow(->) is used to link the arguments to the expression contained in the body.
Without lambda expressions, an interface method looked something like this

@FunctionalInterface //optional
interface MyInterface{
    public void myMethod();
}
public class LambdaExpressionEx{
    public static void main(String args[])
    {
        int variable = 10;
        //implemenmtation without lambda expression
        MyInterface myInterface = new MyInterface(){
            public void myMethod(){
            System.out.println("variable = "+variable);}
                
            };
        myInterface.myMethod();
    }
}

C:\Users\VDG3NA\Documents\images\LambdaEx1-a.JPG

With the help of Lambda expressions now it will look like this:

@FunctionalInterface //optional
interface MyInterface{
    public void myMethod();
}
public class LambdaExpressionEx{
    public static void main(String args[])
    {
        int variable = 10;
        //implemenmtation with lambda expression
        MyInterface myInterface = ()->{
            System.out.println("variable = "+variable);
        };
        myInterface.myMethod();
    }
}

C:\Users\VDG3NA\Documents\images\LambdaEx1-a.JPG

One clear benefit of Lambda Expressions is less lines of code. This can also be observed in the above example. Another advantage is passing behavior as arguments to methods.


2) Functional Interface:


An interface with a single abstract method is a Functional Interface. All such interfaces must have @FuntionalInterface annotation. The implementation of any such method may be treated as a lambda expression. This, like Lambda expressions, enables Functional Programming.

Example: In this example we will use the functional interface Predicate<T> Interface. This interface contains a method test (Object) which returns a Boolean value. 

In this Example, first n -> true is passed to the test method of the Predicate Interface. 


Then we pass n%2, which return true if n%2 is zero i.e. it prints all the even numbers in the list.


import java.util.arrays;
import java.util.List;
import java.util.function.Predicate

public class FuncInterfaceEx {
    public static void main(String args[]) {
    List<Integer> intList = Arrays.asList(1,2,3,4,5,6,7,8,9);
    
    System.out.println("Printing the whole list : ");
    
    //Passing n as parameter
    eval(intList, n-> true);
    System.out.println("Printing even numbers : ");
    eval(intList, n-> n%2 == 0);
    }
    
     public static void eval(List<Integer> intList, Predicate<Integer> predicate)
     {
         for(Integer n : intList)
         {
             if(predicate.test(n)){
                 System.out.println(n + " ");
             }
         }
     }
       
}

C:\Users\VDG3NA\Documents\images\funcInterfaceEx_a.JPG


3)Default and static methods in Interfaces:

The methods in an interface have always been public and abstract. With the Java 8 update, we can now add default and static methods to interfaces.
An interface is mostly implemented in multiple classes. Now consider a scenario where there is a need to add another method to the interface. This was an overhead as all the classes implementing the interface had to now be updated to include the new added method. 
With Java 8’s introduction of default methods, the new method can be added to an interface without the need to implement them in all classes.
This has basically given us a way to add new code without breaking the existing one.

Similarly, even static methods do not need to be implemented in all the classes. The only difference is that as static methods, they cannot be overridden.
Example:

interface MyInterface{
    default void newDefaultMethod(){
        System.out.println("New default method");
    }
    static void newStaticMethod(){
        System.out.println("New static method");
    }
    void existingMethod(String str);
}
public class Example implements MyInterface {
    //existing method implementation
    public void existingMethod(String str){
        System.out.println("String : "+str);
    }
    //There is no need to implement the other methods
    public static void main(String args[]) {
        
        Example obj = new Example();
        
        obj.newDefaultMethod();
        MyInterface.newStaticMethod();
        obj.existingMethod("This is the new java 8 feature");
    }
}


C:\Users\VDG3NA\Documents\images\staticnDefaultEx_a.JPG

4) Collection API Improvements:

  • foreach() method in Iterable:
A collection in Java always requires some way of going over its contents. Java 8 introduces a new forEach() and forEachOrdered() methods for this purpose.

The method signature is as follows:

default void forEach(Consumer<super T>action) 

Examples:

Passing lambda expressions to forEach:

import java.util.ArrayList;
import java.util.List;

public class ForEachEx {
    public static void main(String args[]) {
        
        List<String> gamesList = new ArrayList<String>();
        gamesList.add("Football");
        gamesList.add("Cricket");
        gamesList.add("Baseball");
        System.out.println("----------------Passing lambda expression----------------------")
        gamesList.forEach(games -> System.out.println(games));
    }
}


C:\Users\VDG3NA\Documents\images\foreachEx1_a.JPG

Passing method reference to forEach:
import java.util.ArrayList;
import java.util.List;

public class ForEachEx {
    public static void main(String args[]) {
        
        List<String> gamesList = new ArrayList<String>();
        gamesList.add("Football");
        gamesList.add("Cricket");
        gamesList.add("Baseball");
        System.out.println("----------------Passing method referrence----------------------");
        gamesList.forEach(System.out::println);
    }
}

Response

Similarly, the foreachOrdered method can also be used with method references and lambda expressions. The other new methods added to the Collection API are:
  • forEachRemaining(Consumer action) : Performs action on each remaining element till all elements are processed. This is an Iterator default method
  • removeIf(Predicate filter) : This is a default method in the Collection Interface. It removes all elements if the given condition is satisfied.
  • Spliterator(): This method in Collection can be used to traverse elements sequentially or in parallel.
  • replaceAll(), compute(), merge(): These methods are included in Map.

5)Java Time API:

It was always difficult to work with Date in java as there was never a standard or an API for Date and Time. With Java 8, the entire process has been streamlined.

The major features in the new implementation are:
  • The new Date Time API has all immutable classes.
  • There is a clear separation between the human readable and machine readable time. Separate classes for Date, Time, Timestamp, DateTime, Timezone have been introduced.
  • There is a clarity in the function performed by methods in all the classes. Methods like parse() and format() are defined in all the classes and perform the same function in all.
Examples
  • Here is an example using LocalDate and LocalDateTime class. Similar implementations can be done for LocalTime, LocalDateTime and Instant.This example also shows parsing and formatting which is the most commonly used function.
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class ParseFormatEx {
    public static void main(String args[]) {
        LocalDate date = LocalDate.now();
        System.out.println("Default local date "+date);
        //printing in specific format
        System.out.println(date.format(DateTimeFormatter.ofPattern("d::MMM::uuuu")));
        System.out.println(date.format(DateTimeFormatter.BASIC_ISO_DATE));
        
        LocalDateTime localDateTime = LocalDateTime.now();
        System.out.println("Default LocalDateTime "+localDateTime);
        //printing in specific format
        System.out.println(date.format(DateTimeFormatter.ofPattern("d::MMM::uuuu HH::MM::ss")));
        System.out.println(date.format(DateTimeFormatter.BASIC_ISO_DATE));
        
        Instant timestamp = Instant.now();
        System.out.println("Default Format of Instant "+timestamp);
        
        //Parse
        LocalDateTime dt = LocalDateTime.parse("27::Apr::2014 21::39::48",DateTimeFormatter.ofPattern("d::MMM::uuuu HH::MM::ss"));
        System.out.println("After formatting "+dt);
        
    }
}

C:\Users\VDG3NA\Documents\images\DateTimeEx2_a.JPG



6) Nashorn JavaScript engine:

A new command jjs has been introduced to execute JavaScript on console. To call and interpret the JavaScript code in a Java program, the ScriptEngineManager can be used. Example:


import javax.script.ScriptEngineManager;
import javax.script.ScriptEngine;
import javax.script.ScriptException;

public class JSEngineExample {
    public static void main(String args[]) {
        
        ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
        ScriptEngine nashorn = scriptEngineManager.getEngineByName("nashorn");
        
        String str = "javascriptEx";
        Integer addition = null;
        
        try {
            nashorn.eval("print('" + str + "')");
            addition = (Integer) nashorn.eval("2 + 2");
        }catch(ScriptException e) {
            System.out.println("Error executing script: "+ e.getMessage());
        }
        System.out.println(addition.toString());
    }
}


C:\Users\VDG3NA\Documents\images\nashornEx_a.JPG

Recommended books
If you are in a hurry and want a quick course on the basics of Java 8, then the Java SE 8 for the really Impatient by Cay S. Horstmann is recommended. This book will provide a basic overview of all the features and other improvements.
As Lambda expressions is the most significant update of the release, Java 8 Lambdas: Pragmatic Functional Programming is very useful in getting a thorough insight on this topic.
Java 8 in Action is a book that is highly recommended if a detailed study of the language and its features needs to be done. It covers all the Java 8 features and is especially good for experienced programmers.

If you like this article , please share it with your friend and colleagues.


Thanks for reading

0 comments:

Post a Comment