Java 8 feature - Lambda expression, Functional interface, Default methods, Double colon operator, Steam API, Steam API, Nashron JavaScript

Java 8 feature includes the major improvements and additional features listed below, which improves the java v1.8 as a more standard and less verbose programming language.

  1. Lambda expression  (closure)
  2. Functional interface
  3. Default methods
  4. Predicates
  5. Functions, supplier, consumer
  6. Double colon operator
  7. Steam API
  8. Date and time API(Joda time API)
  9. Nashron JavaScript

1. Lambda expression: 

  • Lamba Expression is a major feature that enables the functional programming benefits in java.
  • Lambda expressions let allows us to express instances of single-method interfaces (referred to as functional interfaces) more compactly.
  • It Is just an anonymous(nameless) function or closure
  • It has no name, no return type, and no modifier
  • -> (arrow symbol) is used to represent the lambda expression
  •  

Ex 1: Convert normal method into a lambda  expression       // pseudo-code

Normal method
public void m1(){
System.out.println("Hello");
}

Lambda expression
() -> System.out.println("Hello");

Ex 2: Take two values as an argument and print sum using a lambda expression.    // pseudo-code

Normal method
public void m1(int a, int b){
System.out.println(a+b);
}

Lambda expression
(int a, int b) -> System.out.println(a+b);
//compiler will guess type in some context
(a, b) -> System.out.println(a+b);

Ex 3: Take a number and return square in Lambda expression.      // pseudo-code

Normal method
public int square(int n){
    return n*n;
}

(int n) -> return n*n;
//compiler will guess type in some context
(n) -> return n*n;
// for only one argument  () are optional

Lambda expression
n -> return n*n;
// no need of return 
n -> n*n;         // converted code

Conclusions:

public void m1(String s){
return s.length();
}

//with lambda expressiopn
s - > s.length();
  1. Takes Any number of arguments 
  2.  In lambda expression for only one parameter, parenthesis () is optional
  3. Based on context, the compiler will guess type automatically.
  4. {} is mandatory for the multiline body as regular

2. Functional interfaces 

How to call/invoke lambda expressions:

Functional interfaces are the concept where we should use lambda expressions only. Rest other places we can’t use lambda expressions.

Note: Throwable is a class name, root for java exception hierarchy

Runnable - thread  ==> run()
Callable - thread  ==> call()
Comparable   == > compareTo();     //-collection
Comparator  == > compare()
Callable  ==> call()

Supply
Predicate
Consumer
Function

SAM == > Single Abstract Method  (SAM)

Interfaces which contain single abstract methods, those methods are considered as functional interfaces.

3. Default Methods

Prior to java v1.8, only abstract methods

From java v1.8 default, and static methods are also allowed,  we can use any number of default and static methods but only one abstract method is allowed.

default void m1(){}
static void m1(){} 
  • Restrictions are only for abstract methods not for default and static methods.
  • The interface does not contain any methods, and by implementing object get some ability to perform some task, considered as a marker interface, have a look below.
Serializable -  
randomAccess -
Cloneable
single ThreadModel

@FunctionalInterface  

  • This annotation came to indicate this interface is a functional interface explicitly
  • In the below example we are using two abstract methods i.e. m1 and m2 hence there will be error @FunctionalInterface will notify, by saying Unexpected @FunctionalInterface annotation multiple non-overriding abstract n\methods found in interface Interf
  • But when we comment m2() then code will compile fine.

Ex 

@FunctionalInterfacean interface Interf
{
public abstract void m1();
public abstract void m2();    
// remove annotation  compile fine with this line -- > no functional interface
// if we add annotation, compiler will give error : Unexpected @FunctionalInterface annotation
// with single abstract method always it is functional interface
// with annotation compiler validates, which is beneficial for programmer
default void m2(){}        // default implementation  and public 
static void m3(){} // static implementation  and public
}

@FunctionalInterface vs inheritance

@FunctionalInterface
interface A(){
public void m1();
}
@FunctionalInterface
Interface B extends A(){       // valid
// by default public void m1(); is available here
public void m1();     // putting this code will compile because  m1 is overriding 
public void m2();     // putting this, code will not compile because  m2   is another abstract method but by removing annotation from B, code will compile fine.
}

() -> (“Hello”);   // FunctionalInterface will provide the reference

Ex1 

//Normal Methods
package com.company;

class Test {
    public static void main(String[] args) {
//        Demo d = new Demo();
//        i.m1();
        Interf i = new Demo();
        i.m1();
    }
}

interface Interf {
    void m1();
}

class Demo implements Interf {
    public void m1() {
        System.out.println("m1 implementation");
    }
}

//Lambda Expression
package com.company;

class Test {
    public static void main(String[] args) {
        Interf i = () -> System.out.println("m1 lambda implementation");
        i.m1();
    }
}

interface Interf {
    void m1();
}

Ex2

//Normal Methods
package com.company;

class Test {
    public static void main(String[] args) {
        Interf i = new Demo();
        i.add(10, 20);
    }
}

interface Interf {
    void add(int a, int b);
}


class Demo implements Interf {
    public void add(int a, int b) {
        System.out.println("The sum is:" + (a + b));
    }
}

o/p Output: the sum is:” 30

// Lambda Expression
package com.company;

class Test {
    public static void main(String[] args) {
        Interf i = (a, b) -> System.out.println("The sum is:" + (a + b));
        i.add(10, 20);
    }
}

interface Interf {
    void add(int a, int b);
}


Output: the sum is: 30

Ex3 With the default and static 

//Normal Methods
package com.company;

class Test {
    public static void main(String[] args) {
        Interf i = new Demo();
        i.add(10, 20);
        i.m1();
        Interf.m2();
    }
}

interface Interf {
    void add(int a, int b);

    default void m1() {
        System.out.println("Default Method");
    }

    static void m2() {
        System.out.println("static method");
    }
}

class Demo implements Interf {
    public void add(int a, int b) {
        System.out.println("The sum is:" + (a + b));
    }
}

Output: the sum is:
The sum is:30
Default Method
static method

//Lambda Expression
package com.company;

class Test {
    public static void main(String[] args) {
        Interf i = (a, b) -> System.out.println("With lambda the sum is: " +(a+b));
        i.add(10, 20);
        i.m1();
        Interf.m2();
    }
}

interface Interf {
    void add(int a, int b);

    default void m1() {
        System.out.println("Default Method");
    }

    static void m2() {
        System.out.println("static method");
    }
}

Output: the sum is:
With lambda the sum is: 30
Default Method
static method

Ex4  case of two abstract methods.

//Lambda Expression
package com.company;

class Test {
    public static void main(String[] args) {
        Interf i = (a, b) -> System.out.println("With lambda the sum is: " +(a+b));
        i.add(10, 20);
    }
}

interface Interf {
    void add(int a, int b);
    void sub(int a, int b);
    // a, b map with add or sub --- ambiguity occur
    //Interf is not a functional interface
}

Output:
java: incompatible types: com.company.Interf is not a functional interface
    multiple non-overriding abstract methods found in interface com.company.Interf

Ex4  square

//Normal Method
package com.company;

class Test {
    public static void main(String[] args) {
        Interf i = new Demo();
        System.out.println("The square is: " + i.square(20));
    }
}

interface Interf {
    int square(int n);
}

class Demo implements Interf {
    public int square(int n) {
        return n * n;
    }
}

Output: the sum is:
The square is: 400


// Lambda Expression
package com.company;

class Test {
    public static void main(String[] args) {
        Interf i = n -> n * n;
        //Interf i = n -> { return n*n;}; return must be required and expn should end with ;
        System.out.println("Square is " + i.square(20));
    }
}

interface Interf {
    int square(int n);
}

output:
Square is 400

Ex5  thread runnable

//Normal method
package com.company;

class Test {
    public static void main(String[] args) {
        MyRunnable r = new MyRunnable();
        Thread t = new Thread(r);
        t.start();
        for(int i=0; i<3; i++){
            System.out.println("Main Thread");
        }
    }
}

class MyRunnable implements Runnable {
    public void run() {
        for (int i = 0; i < 3; i++) {
            System.out.println("Child Thread");
        }
    }
}

output :
Main Thread
Main Thread
Main Thread
Child Thread
Child Thread
Child Thread

//Lambda expression
package com.company;

class ThreadDemo {
    public static void main(String[] args) {
        Runnable r = () -> {
            for (int i = 0; i < 3; i++){
                System.out.println("Child Thread with lambdas");
            }};

        Thread t = new Thread(r);
        t.start();
        for(int i=0; i<3; i++){
            System.out.println("Main Thread");
        }
    }

}
output:
Main Thread
Child Thread with lambdas
Child Thread with lambdas
Child Thread with lambdas
Main Thread
Main Thread

Lambda expression does not generate any .class file bydefault.

if(x  > 10){}
x=x+1
accept(students){}
getConnection()
Java.util.function => general libraries 
Lambda expression does not generate .class file default.

Ex 6 Array List example

Please remember

Comparator 

Int compare (Object o1, Object  o2)
Returns -ve iff o1 has  to come before o2
Return +ve iff o1 has to come after o2
Returns 0 iff o1 and o2 are equal
//Normal method
package com.company;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

class Test {
    public static void main(String[] args) {
        ArrayList l = new ArrayList();
        l.add(30);
        l.add(20);
        l.add(40);
        //System.out.println(l);
        Collections.sort(l, new MyComparator());
        System.out.println(l);
    }
}

class MyComparator implements Comparator {
    public int compare(Integer i1, Integer i2) {
//Return (i1 i2) ? +1 : 0;
        if (i1 < i2) {
            return -1;
        } else if (i1 > i2) {
            return +1;
        } else {
            return 0;
        }
    }
}
output :
[20, 30, 40]

// Normal method optimized
package com.company;

import java.util.ArrayList;
import java.util.Comparator;

class Test {
    public static void main(String[] args) {
        ArrayList l = new ArrayList();
        l.add(30);
        l.add(20);
        l.add(40);
        l.sort(new MyComparator());
        System.out.println(l);
    }
}

class MyComparator implements Comparator {
    public int compare(Integer i1, Integer i2) {
        return i1.compareTo(i2);
    }
}

output :
[20, 30, 40]
//Lambda expression
package com.company;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

class Test {
    public static void main(String[] args) {
        ArrayList l = new ArrayList();
        l.add(30);
        l.add(20);
        l.add(40);
        System.out.println(l);
        Comparator c= (i1, i2) -> (i1 < i2) ? -1 : (i1>i2) ? +1 : 0;
        Collections.sort(l, c);
        System.out.println("Sorted list " + l);
    }
}
output :
[30, 20, 40]
Sorted list [20, 30, 40]

//Lambda expression optimized
package com.company;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

class Test {
    public static void main(String[] args) {
        ArrayList l = new ArrayList<>();
        l.add(30);
        l.add(20);
        l.add(25);
        l.add(40);
        l.add(45);
        System.out.println(l);
        Comparator c= Integer::compareTo;
        l.sort(c);
        System.out.println("Sorted list " + l);
        // data one by one
        l.forEach(System.out::println);
        // even number list
        List l2 = l.stream().filter(i -> i%2==0).collect(Collectors.toList());
        System.out.println(l2);
    }
}
Output :
[30, 20, 25, 40, 45]
Sorted list [20, 25, 30, 40, 45]
20
25
30
40
45
[20, 30, 40]

Ex 7  Anonymous inner class

//example one
package com.company;

class Test {
    public static void main(String[] args) {
        Employee e = new Employee("me", 100);
        System.out.println(e);

    }
}

class Employee {
    String name;
    int eno;

    Employee(String name, int eno) {
        this.name = name;
        this.eno = eno;
    }
    public String toString() {
       return name + " " + eno;
    }
}
Output :
me 100

// example two
package com.company;

import java.util.ArrayList;

class Test {
    public static void main(String[] args) {
        ArrayList l = new ArrayList();
        l.add(new Employee("me", 786));
        l.add(new Employee("sanjay", 756));
        l.add(new Employee("software", 5565));
        l.add(new Employee("technology", 5454));
        System.out.println(l);
    }
}

class Employee {
    String name;
    int eno;

    Employee(String name, int eno) {
        this.name = name;
        this.eno = eno;
    }

    public String toString() {
        return name + " " + eno;
    }
}
Output :
[me 786, sanjay 756, software 5565, technology 5454]

//example three
package com.company;

import java.util.ArrayList;
import java.util.Collections;

class Test {
    public static void main(String[] args) {
        ArrayList l = new ArrayList<>();
        l.add(new Employee("me", 786));
        l.add(new Employee("sanjay", 756));
        l.add(new Employee("software", 5565));
        l.add(new Employee("technology", 5454));
        Collections.sort(l, (e1, e2) -> (e1.enoe2.eno) ?  1 : 0);
        System.out.println(l);
    }
}

class Employee {
    String name;
    int eno;

    Employee(String name, int eno) {
        this.name = name;
        this.eno = eno;
    }

    public String toString() {
        return name + " " + eno;
    }

}
output:
[sanjay 756, me 786, technology 5454, software 5565]
  • In collection comparable and comparator  we use for sorting we can use for 

Anonymous Inner classes vs Lambda Expressions

The class without having name are anonymous inner class

Thread t = new Thread();

Thread t = new Thread(){
…...
};     

//We are writing a class that extends Thread class i.e. creating child class for the Thread and for the child class we are creating the object.
Runnable r = new Runnable();  // X interface
Runnable r = new Runnable(){
….
}

Ex.  8   lambda expression can be used to reduce the code of the anonymous class

//Normal Method
package com.company;

class Test {
    public static void main(String[] args) {
        Runnable r = new Runnable() {
            public void run() {
                for (int i = 0; i < 3; i++) {
                    System.out.println("Child Thread");
                }
            }
        };

        Thread t = new Thread(r);
        t.start();
        for (int i = 0; i < 3; i++) {
            System.out.println("Main Thread");
        }
    }
}
output:
Main Thread
Main Thread
Main Thread
Child Thread
Child Thread
Child Thread
Lambda expression
package com.company;

class Test {
    public static void main(String[] args) {
        Runnable r = () -> {
            for (int i = 0; i < 3; i++) {
                System.out.println("Child Thread");
            }
        };

        Thread t = new Thread(r);
        t.start();
        for (int i = 0; i < 3; i++) {
            System.out.println("Main Thread");
        }
    }
}
output :
Main Thread
Main Thread
Main Thread
Child Thread
Child Thread
Child Thread
Interface A{
m1();
m2();
}
  • Lambda Expression is applicable for only one abstract method that is can implement only interface having only one abstract method.
  • Anonymous Inner Class, everywhere Lambda Expression can be used where Anonymous Inner Class contains only  Single Abstract Method(SAM).

Anonymous Inner Class can extend normal class, an abstract class, can implement an interface which contains any number of the abstract method

A a = new A{
  public void m1(){
  }
  public void m2(){
  }
}

4. Default method

  • Until 1.7v - every method present inside the interface is always: public and abstract
Void m1()
Public void m1()
Public abstract void m1()

Related to methods:

 From 1.8v: default and static method,  1.9v private method

Variables:  Variable is the same, with no enhancement related to variables. 

public static final     // for all versions till 1.9 v

Default method | Virtual Extension method | defender Method

Ex. Pseudocode

interface I {
    void m1();
    void m2();
    void m3();   // X error,   adding this code will not be compiled, cause there is no implementation
    default void m3();   // works perfectly not need to implement, or if wish or can be overridden, or can be ignored.
}

class Test1 implements I {
    public void m1() {
    }

    public void m2() {
    }
}

class Test2 implements I {
    public void m1() {
    }

    public void m2() {
    }
}
  • Compulsory provide the implementation

Default method - without affecting implementation classes if we want to add a new method to the interface such a type of method is known as the default method.

Ex  1

package com.company;

public interface Interf {
    default void m3(){
          // we can't declare default method in class, there is changed meaning
        System.out.println("default method implementation");
    }

    class Test implements Interf{
        public void m1() {    // can’t use default method within the class, treated as a modifier in a class
            System.out.println("Overriding default method implementation");
        }
    }

    public static void main(String[] args){
        Test t = new Test();
        t.m1();
    }

}
output:
Overriding default method implementation

Ex 2

interface Interf {
    default void m3() {
        System.out.println("Default Method");
    }

    default int hashCode()   //   Already available to every implementation method, so it's unnecessary.
    {
        return 10;
    }
}

class Test implements Interf {
}
output:
java: default method hashCode in interface com.company.Interf overrides a member of java.lang.Object

 

Conclusion 1: 

  • Object class method, we can not implement as default method because this object class method is by default available to all implementations so we are not allowed to override or reimplement.

Multiple inheritances

Diamond access problem, ambiguity problem with multiple inheritances.

package com.company;

class Test extends p1, p2 {
         // X    java: '{' expected
    public static void main(String[] args) {
        Test t = new Test();
        t.m1();   // ambiguity problem here X
    }
}

class p1 {
    public void m1() {
        System.out.println("p1 method");
    }
}

class p2 {
    public void m1() {
        System.out.println("p2 method");
    }
}
Output :
D:\workspace\BlogCodeTest\src\com\company\Main.java:3:22
java: '{' expected

Ex 

package com.company;

class Test implements Left, Right {

    public static void main(String[] args) {
        Test t = new Test();
        t.m1();
    }
}

interface Left {
    default void m1() {
        System.out.println("Left Interface m1 method");
    }
}

interface Right {
    default void m1() {
        System.out.println("Right Interface m1 method");
    }
}
// we can't call as class Test implements Left, Right{}
D:\workspace\BlogCodeTest\src\com\company\Main.java:3
java: class com.company.Test inherits unrelated defaults for m1() from types com.company.Left and com.company.Right

//Solution
package com.company;

class Test implements Left, Right {
    public void m1() {
                             // we required to provide implementation
        System.out.println("Our own m1 method");   // overriding solves multiple inheritance by default method
        Left.super.m1();
        Right.super.m1();
    }
    
    public static void main(String[] args) {
        Test t = new Test();
        t.m1();
    }
}

interface Left {
    default void m1() {
        System.out.println("Left Interface m1 method");
    }
}

interface Right {
    default void m1() {
        System.out.println("Right Interface m1 method");
    }
}
output :
Our own m1 method
Left Interface m1 method
Right Interface m1 method
  • If two interfaces contain default methods with the same implementation than the implementation class has to override.
classinterface

Costly,  

Class Test{

m1(){}

}

Never contains constructor, static class, instance block,

We never create an object

// There is onluy one ways to call only by using interface name
package com.company;

interface Interf {
    public static void m1() {
        System.out.println("Interface static method");
    }

    class Test implements Interf {
        public static void main(String[] args) {
            Interf.m1();                 // ways to call only by using interface name only
            m1();                        //     X
            Test.m1();                   //     X
            Test t = new Test();         //     X
            t.m1();                      //     X
        }
    }

}

Ex   We can define general utility methods by the interface, not need to go for class

package com.company;

interface Interf {
    public static void main(String[] args) {
        System.out.println("Interface with main method");
    }
}
output:
Interface with main method

package com.company;

interface Interf {
    static void main(String[] args) {
        System.out.println("Interface with main method");
    }
    // if everything is static no way related to the object, there is no need to use class, happily we can use interfaces.
    sum(int a, int b) {
        System.out.println(a + b);
    }
}
  • The static methods which are declared inside the interface are by default not available to the implementation classes, compulsory we have to by using interface name only.

Predefined functional interfaces

Predicate
Function
Consumer
Supplier
---------------------
Two arguments predefined functional interface
Bipredicate
Bifunction
Biconsumer 
-------------------------
Primitive functional interface
-------------------------------
intPredicate
IntFunction
intConsumer
…….

The Java.util.function package contains all the methods present.

5. Predicate  // boolean value function

java.util.function.Predicate

  • Conditional check

public abstract  boolean  test(T t);

interface Predicate {
    public boolean test(T t);
}
Normal Way
    public boolean test(Integer 1) {
        if (i % 2) {
            return true;
        } else {
            return false;
        }
    }
With Lambda expression
(Integer I) -> I%2 ==0
or
I -> I%2==0
// pseudocode
package com.company;

import java.util.function.Predicate;

class Test {
    public static void main(String[] args) {
        Predicate p1 = i -> i % 2 == 0;
        System.out.println(p1.test(10);
        System.out.println(p1.test(15);
//        Predicate p1=e -> salary>100000 && e.something==true;
//        System.out.println(p1.test(e);
//        p1.and(p2).test(34);
//        p1.or(p2);
//        p1.negate();
    }
}

Ex. 1.

package com.company;

import java.util.function.Predicate;

class Test {
    public static void main(String[] args) {
        String[] s= {"apple", "computer", "book", "computer software"};
        Predicate p = s1 -> s1.length() > 5;
        //Predicate p = s1 -> s1.length()%2==0;
        for(String s1 : s){
            if(p.test(s1)){
                System.out.println(s1);
            }
        }
    }
}
output:
computer
computer software

output: by uncommenting //Predicate p = s1 -> s1.length()%2==0;
computer
book

Ex. 2

package com.company;

import java.util.ArrayList;
import java.util.function.Predicate;

class Test {
    public static void main(String[] args) {
     ArrayList l = new ArrayList<>();
     l.add(new Employee("sanjay", 20000));
     l.add(new Employee("Employee A", 50000));
     l.add(new Employee("Employee B", 60000));
     l.add(new Employee("Employee C", 70000));
     Predicate p = employee -> employee.salary>30000;
     for(Employee e1 : l){
         if(p.test(e1)){
             System.out.println(e1.name + ":" + e1.salary);
         }
     }
    }
}

class Employee{
    String name;
    double salary;
    Employee(String name, double salary){
        this.name=name;
        this.salary=salary;
    }
}

output:
Employee A:50000.0
Employee B:60000.0
Employee C:70000.0

Ex 3

package com.company;
import java.util.function.Predicate;

class Test {
    public static void main(String[] args) {
     int[] x = {0, 5, 10, 15, 20, 25, 30, 35, 40, 45};
     Predicate p1 = i -> i%2==0;
     Predicate p2 = i -> i>10;
     // and(), or(), negate()   can be used to test the condition.
        System.out.println("The numbers which are even and > 100 are :");
        for(int x1 : x){
            if(p1.and(p2).test(x1)){
                System.out.println(x1);
            }
        }
    }
}
output:
The numbers which are een and > 100 are :
20
30
40

6. Functions, supplier, consumer

  • function chaining is simply applying other functions in the output of the other function.
f1.andThen(f2).apply(i)    //first f1 andthen f2       
f1.compose(f2).apply(i)    //first f2 and then f1

java.util.function.Function

  • To perform some operation and produce some result function can be used.

Ex. 1

package com.company;

import java.util.function.Function;

class Test {
    public static void main(String[] args) {
        Function function = i -> i*i;
        System.out.println(function.apply(5));
        System.out.println(function.apply(20));
    }
}
output:
25
400

Ex.2

package com.company;

import java.util.function.Function;

class Test {
    public static void main(String[] args) {
        Function function = s -> s.length(); 
        System.out.println(function.apply("software with lambda "));
        
        Function function1 = String::length;
        System.out.println(function.apply("software with method reference"));
        
        Function function = s -> s.toUpperCase();
        System.out.println(function.apply("software in upper case"));
    }
}
output:
18
30
SOFTWARE IN UPPER CASE

Ex. 3

package com.company;

import java.util.function.Function;
import java.util.function.Predicate;

class Test {
    public static void main(String[] args) {

        Function function = s -> {
            int marks = s.marks;
            String grade = "";
            if (marks >= 80) grade = "A[Distinction]";
            else if (marks >= 60) grade = "B[First Division]";
            else if (marks >= 45) grade = "C[Second Division]";
            else if (marks >= 35) grade = "D[Third Division]";
            else grade = "Failed";

            return grade;
        };
        //Predicate predicate = s -> s.marks > 80;
        Student[] s = {
                new Student("Student", 90),
                new Student("Student A", 65),
                new Student("Student B", 65),
                new Student("Student C", 40),
                new Student("Student D", 25)
        };

        for (Student s1 : s) {
            //if (predicate.test(s1)) {
                System.out.println("Student Name" + s1.name);
                System.out.println("Student Marks" + s1.marks);
                System.out.println("Student Grade" + function.apply(s1));
                System.out.println();
            //}
        }
    }
}

class Student {
    String name;
    int marks;

    Student(String name, int marks) {
        this.name = name;
        this.marks = marks;
    }
}
output:
Student NameStudent
Student Marks90
Student GradeA[Distinction]

Student NameStudent A
Student Marks65
Student GradeB[First Division]

Student NameStudent B
Student Marks65
Student GradeB[First Division]

Student NameStudent C
Student Marks40
Student GradeD[Third Division]

Student NameStudent D
Student Marks25
Student GradeFailed
output:    
// marks with uncommenting commented line
Student NameStudent
Student Marks90
Student GradeA[Distinction]

java.util.function.Consumer

  • Takes some input and returns nothing
  • Methods applicable and returns type
interface Consumer{
     public vodi accept(T t);
}

Ex. 1

package com.company;

import java.util.function.Consumer;

class Test {
    public static void main(String[] args) {
        Consumer consumer = s -> System.out.println(s);
        Consumer consumer1 = System.out::println; // method reference
        consumer.accept("mesanjay");
        consumer1.accept("software");
    }
}
output:
mesanjay
software

java.util.function.Supplier

  • Just supply required objects and won't take any input
interface Supplier{
		public ReturnType get();
}

Ex. 1

package com.company;

import java.util.Date;
import java.util.function.Supplier;

class Test {
    public static void main(String[] args) {
        Supplier s1 = () -> new Date();
        Supplier s = Date::new;   // method reference
        System.out.println(s.get());
        System.out.println(s1.get());
    }
}
output:
Sat Oct 03 18:09:49 NPT 2020
Sat Oct 03 18:09:49 NPT 2020

Ex 2

package com.company;

import java.util.function.Supplier;

class Test {
    public static void main(String[] args) {
        Supplier s = () -> {
            String otp = "";
            for(int i =0; i<6 ; i++){
                otp = otp+(int)(Math.random()*10);
            }
            return otp;
        };
        System.out.println("Random otp is : " +s.get());
    }
}
output:
Random otp is : 601488

// code optimized
package com.company;
import java.util.function.Supplier;

class Test {
    public static void main(String[] args) {
        Supplier s = () -> {
            StringBuilder otp = new StringBuilder();
            for(int i =0; i<6 ; i++){
                otp.append((int) (Math.random() * 10));
            }
            return otp.toString();
        };
        System.out.println("Random otp is : " +s.get());
    }
}
output:
Random otp is : 601488
Summary
-----------------------------------------------------------------------------
predicate: Take some input and perform some conditional check
Function: Take some input, perform some operational and returns the output
Consumer: Accept some input and perform some operation and do not return anything

Two input arguments

ByPredicate 
BiFunction   
BiConsumer
There is no BiSupplier

ByPredicate 

  •  It is the same as the predicate except that it will take 2 input arguments.
  • Please checksum of two given number is even or not   ---> ByPredicate
   interface BiPredicate {
        public boolean test(T1 t2, T2 t2);
        // remaining default and static method are same
    }

Ex 

package com.company;

import java.util.function.BiPredicate;

class Test {
    public static void main(String[] args) {
        BiPredicate p = (a, b) -> (a + b) % 2 == 0;
        System.out.println(p.test(10, 20));
        System.out.println(p.test(11, 20));
    }
}
output:
true
       // 10+ 20  = 30     30%2 == 0 which is true
false      // 11+ 20  = 31     31%2 != 0 which is false

BiFunction  // use two input

interface BiFunction
{
public R apply(T t, U u);
//default method andThen()
}

Ex 

package com.company;

import java.util.ArrayList;
import java.util.function.BiFunction;

class Test {
    public static void main(String[] args) {
        ArrayList l = new ArrayList<>();
        BiFunction f=(eno, name)-> new Employee(eno, name);
        //Employee e1 = f.apply(100, "mesanjay");
        l.add(f.apply(100, "Employee A"));
        l.add(f.apply(200, "Employee B"));
        l.add(f.apply(300, "Employee C"));
        l.add(f.apply(400, "Employee D"));

        for(Employee e : l) {
            System.out.println("Employee Number: " + e.eno);
            System.out.println("Employee Name: " + e.name);
            System.out.println();
        }
    }
}

class Employee {
    int eno;
    String name;

    Employee(int eno, String name) {
        this.eno = eno;
        this.name = name;
    }
}
output:
Employee Number: 100
Employee Name: Employee A

Employee Number: 200
Employee Name: Employee B

Employee Number: 300
Employee Name: Employee C

Employee Number: 400
Employee Name: Employee D

BiConsumer

  • Provide two input argument and perform some required operation 
package com.company;

import java.util.ArrayList;
import java.util.function.BiConsumer;

class Test {
    public static void main(String[] args) {
        ArrayList l = new ArrayList<>();
        populate(l);
        BiConsumer c = (e, d) -> e.salary=e.salary + d;
        for (Employee e : l) {
            c.accept(e,500.0);
        }

        for (Employee e : l) {
            System.out.println("Employee Name : " + e.name);
            System.out.println("Employee Salary: " + e.salary);
            System.out.println();
        }
    }

    public static void populate(ArrayList l) {
        l.add(new Employee("Employee A", 1000));
        l.add(new Employee("Employee B", 5000));
        l.add(new Employee("Employee C", 6000));
        l.add(new Employee("Employee D", 7000));
    }
}

class Employee {
    String name;
    double salary;

    Employee(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }
}
output:
Employee Name : Employee A
Employee Salary: 1500.0

Employee Name : Employee B
Employee Salary: 5500.0

Employee Name : Employee C
Employee Salary: 6500.0

Employee Name : Employee D
Employee Salary: 7500.0

There is no BiSupplier

6. Double colon operator -  code reusability 

  • Methods(static and instance) and constructor reference by using:: operator
  • For functional interface case only:: (double colon operator) can be used.
  • Aalternative for lambda expression 

Static for the static method:

classname::methodname

Instance method:

objectreference::methodname

Ex 1    Reference to a static method

package com.company;

interface Callable{
    void call();
}
public class MethodReference {
    public static void test() {
        System.out.println("static method test");
    }

    public static void main(String[] args) {
        // Referring static method
        Callable callable  = MethodReference::test;
        // Calling interface method
        callable.call();
    }
}
output:
static method test

Ex 2 Reference to an instance method

package com.company;

public class MethodReference {
    public static void ThreadStatus(){
        System.out.println("Thread is running...");
    }
    public static void main(String[] args) {
        Thread thread=new Thread(MethodReference::ThreadStatus);
        thread.start();
    }
}
output:
Thread is running...

Ex3 Reference to a constructor

  • To create an object at the time of object creation
package com.company;

import java.util.function.BiFunction;

public class MethodReference {
    public static void main(String[] args) {
        BiFunction adder = Calculate::add;
        int result = adder.apply(50, 60);
        System.out.println(result);
    }
}

class Calculate{
    public static int add(int a, int b){
        return a+b;
    }
}
output:
110
Method ReferenceLambda expressionconstructor reference

Interf i = Test::m1;

Runnable r = Test::m2;

Interf i = ()-> new Sample();

Interf i = Sample::new;

i.m1();

7. Streams API

  • The stream is an interface present inside java.util.stream
  • The collection  → we can use the collection to represent a group of the object as a single entity
  • Stream → To process the object from the collection
  • Stream s = c.stream();     // where c is collection

Ex. 1

package com.company;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class Test {
    public static void main(String[] args) {
        ArrayList marks = new ArrayList<>();
        marks.add(0);
        marks.add(5);
        marks.add(10);
        marks.add(15);
        marks.add(20);
        marks.add(25);
        marks.add(30);
        System.out.println(marks);
        List updatedMarks =
                marks.stream().map(s -> s + 5).collect(Collectors.toList());
        System.out.println(updatedMarks);
    }
}
output:
[0, 5, 10, 15, 20, 25, 30]
[5, 10, 15, 20, 25, 30, 35]

ex2

Map - > for every object if we want to perform some function and we want some result object

package com.company;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class Test {
    public static void main(String[] args) {
        ArrayList marks = new ArrayList<>();
        marks.add(0);
        marks.add(5);
        marks.add(10);
        marks.add(65);
        marks.add(20);
        marks.add(25);
        System.out.println(marks);       // 0,5,10,15,20,25
        List updatedMarks = marks.stream().map(i -> i + 5).collect(Collectors.toList());
        System.out.println(updatedMarks);
//use count() method
        long noOfFailedStudents = marks.stream().filter(m -> m < 35).count();
        System.out.println(noOfFailedStudents);
// sorted()
        List sortedList = marks.stream().sorted().collect(Collectors.toList());
        System.out.println(sortedList);
// comparator()
        List sortedList1 = 
                marks.stream().sorted(((i1, i2) -> (i1 > i2) ? -1 : 0)).collect(Collectors.toList());
        System.out.println(sortedList1);
// toArray()
        Integer[] i = marks.stream().toArray(Integer[]::new);
        System.out.println(i);
// forEach(function)
        marks.stream().forEach(System.out::println);

    }
}
output:
[0, 5, 10, 65, 20, 25]
[5, 10, 15, 70, 25, 30]
5
[0, 5, 10, 20, 25, 65]
[65, 25, 20, 10, 5, 0]
[Ljava.lang.Integer;@10f87f48
0
5
10
65
20
25

Note: 

filter(Predicate)  // boolean value function

Map(function)   // generate new value by doing some operation

8. Date and time API(Joda time API) 

  • Date, Calendar, timeStamp…..1.7v   performance, and convenience are not good
  • Date and time API is also named Joda time because it is developed joda.org.
  • Joda-Time provides a quality replacement for the Java date and time classes.
  • Joda-Time is the de facto standard date and time library for Java prior to Java SE 8. Users are now asked to migrate to java.time (JSR-310).
// Current Date and Time
package com.company;

import java.time.LocalDate;
import java.time.LocalTime;

class Test {
    public static void main(String[] args) {
        LocalDate date = LocalDate.now();
        System.out.println(date);
        LocalTime time = LocalTime.now();
        System.out.println(time);
    }
}
output:
2020-10-03
18:50:44.709
//Current date format
package com.company;

import java.time.LocalDate;

class Test {
    public static void main(String[] args) {
        LocalDate date = LocalDate.now();
        System.out.println(date);
        int dd = date.getDayOfMonth();
        int mm = date.getMonthValue();
        int yyyy = date.getYear();
        System.out.println(dd + "---" + mm + "----" + yyyy);
        System.out.printf("%d-%d-%d", dd, mm, yyyy);       //21-7-2020
        System.out.println("\n");
        System.out.printf("%d-%d-%d", yyyy, mm, dd);       //2020-7-21
    }
}
output:
2020-10-03
3---10----2020
3-10-2020

2020-10-3
//Current Time format
package com.company;

import java.time.LocalTime;

class Test {
    public static void main(String[] args) {
        LocalTime time = LocalTime.now();
        System.out.println(time);
        int h= time.getHour();
        int m= time.getMinute();
        int s= time.getSecond();
        int n = time.getNano();
        System.out.printf("%d:%d:%d:%d", h,m,s,n);       //15:41:25:87
    }
}
output:
18:57:58.459
18:57:58:459000000
For both date and time -> 
package com.company;

import java.time.LocalDateTime;

class Test {
    public static void main(String[] args) {
        LocalDateTime dt = LocalDateTime.now();
        System.out.println(dt);
        int dd = dt.getDayOfMonth();
        int mm = dt.getMonthValue();
        int yyyy = dt.getYear();
        System.out.printf("%d-%d-%d", yyyy,mm,dd);       //2020-7-21
        int h= dt.getHour();
        int m= dt.getMinute();
        int s= dt.getSecond();
        int n = dt.getNano();
        System.out.printf("%d:%d:%d:%d", h,m,s,n);       //15:41:25:87
    }
}
output:
2020-10-03T18:59:02.261
2020-10-318:59:2:261000000

Represent Particular date of time

  • LocalDateTime dt = LocalDateTime.of(yyyy, mm, dd, h, m, s, n);

Ex. 

package com.company;

import java.time.LocalDateTime;

class Test {
    public static void main(String[] args) {
        LocalDateTime dt = LocalDateTime.of(1998, 05, 24, 12, 34);
//        can be used 05 replacing Month.MAY
        System.out.println(dt);
        System.out.println("After 6 months: " + dt.plusMonths(5));
        System.out.println("Before 6 months: " + dt.minusMonths(5));
    }
}
output:
1998-05-24T12:34
After 6 months: 1998-10-24T12:34
Before 6 months: 1997-12-24T12:34
//Period
package com.company;

import java.time.LocalDate;
import java.time.Period;

public class Test {
    public static void main(String[] args) {
        LocalDate birthDay= LocalDate.of(1998, 05, 24);
        LocalDate today= LocalDate.now();
        Period p = Period.between(birthDay, today);
        System.out.printf("Age is : %d years %d months and %d days", p.getYears(), p.getMonths(), p.getDays());
    }
} 
output:
Age is : 22 years 4 months and 9 days


// add year in year
package com.company;

import java.time.LocalDate;
import java.time.Period;

public class Test {
    public static void main(String[] args) {
        LocalDate passedDay= LocalDate.of(1998+60, 05, 24);
        LocalDate today= LocalDate.now();
        Period p1 = Period.between(today, passedDay);
        int d = p1.getYears()*365 + p1.getMonths()*30 +p1.getDays();
        System.out.printf("Test Life span On earth only %d days", d);
    }
}

output:

Test Life span On earth only 13736 days
//Year class
package com.company;

import java.time.Year;
import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("Enter year number");
        int n = sc.nextInt();
        Year y = Year.of(n);
        if (y.isLeap()) {
            System.out.printf("Yes, %d is leap year ", n);
        } else {
            System.out.printf("No, %d is not leap year ", n);
        }
    }
}
output:
Enter year number
> 2020
                            // user input
Yes, 2020 is leap year
//ZoneId class
package com.company;

import java.time.ZoneId;
import java.time.ZonedDateTime;

public class Test {
    public static void main(String[] args) {
        ZoneId zone = ZoneId.systemDefault();
        System.out.println(zone);

        ZoneId la= ZoneId.of("America/Los_Angeles");
        ZonedDateTime dt = ZonedDateTime.now(la);
        System.out.println(dt);
    }
}

output:

Asia/Katmandu
2020-10-03T09:14:36.713-07:00[America/Los_Angeles]

9. Nashorn Javascript

  • A new javascript engine is introduced, to replace the previous (till v1.7) javascript engine Rhino.
  • Nashorn provides better performance, as it directly compiles the code in memory and passes the byte code to JVM.
  • Nashorn Javascript engine can either be used programmatically from java programs or by utilizing the cmd line tool jjs located in program files/ java / jdk_version/bin/jjs

Use :

  1. By cmd tool 
  • Command line tool, jjs located in program files/ java / jdk_version/bin/jjs
print(“hello world”);
quit();

2. In java program

Ex1

package com.company;

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

public class Main {

    public static void main(String[] args) throws ScriptException {
        ScriptEngineManager sem = new ScriptEngineManager();
        ScriptEngine engine = sem.getEngineByName("nashorn");
        engine.eval("print('Hello World')");
    }
}
output:
Hello World

//with try catch
package com.company;

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

public class Main {

    public static void main(String[] args) {
        ScriptEngineManager sem = new ScriptEngineManager();
        ScriptEngine engine = sem.getEngineByName("nashorn");
        try {
            engine.eval("print('Hello World')");
        } catch (ScriptException e) {
            e.printStackTrace();
        }
    }
}
output:
Hello World

ex2

// create a javascript file in src named as demo.js
print("Hello world from java script file");

Let's include the above file by providing an absolute path or relative path as below

package com.company;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.io.FileNotFoundException;
import java.io.FileReader;

public class Main {

    public static void main(String[] args) {
        ScriptEngineManager sem = new ScriptEngineManager();
        ScriptEngine engine = sem.getEngineByName("nashorn");
        try {
            //engine.eval("print('Hello World')");
            engine.eval(new FileReader("D:\\nashronJava8\\src\\demo.js"));  // absolute path
            engine.eval(new FileReader("src\\demo.js"));                    // relative path
        } catch (ScriptException | FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}
output:
Hello world from java script file
      // from absolute path
Hello world from java script file      // from relative path

ex3

//we can create a js file in src folder named as demo1.js
var fun1 = function (name){
    print("Hello, From "+name );
    return "Greeting from javaScript";
}
package com.company;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.io.FileNotFoundException;
import java.io.FileReader;

public class Main {

    public static void main(String[] args) {
        ScriptEngineManager sem = new ScriptEngineManager();
        ScriptEngine engine = sem.getEngineByName("nashorn");
        try {
            engine.eval(new FileReader("src\\demo1.js"));  // relative path
            Invocable invocable = (Invocable) engine;
            Object result = invocable.invokeFunction("fun1", "mesanjay");
            System.out.println(result);
        } catch (NoSuchMethodException | FileNotFoundException | ScriptException e) {
            e.printStackTrace();
        }
    }
}
output:
Hello, From mesanjay
Greeting from javaScript

 I tried to explain all the major concepts of java 8 features. If any concept is not included or there are any typos, then please let me know.  The complete documentation is available here https://www.oracle.com/java/technologies/javase/8-whats-new.html.

Thank you.

Leave a comment now