Java 8 Concepts with Examples

Java 8 new features 

1. Lambda Expressions

A lambda expression is an anonymous function. A function that doesn’t have a name and doesn’t belong to any class. so compiler does not create .class file.

Used to provide the implementation of an interface which has functional interface 

  //Syntax of lambda expression

(parameter_list) -> {function_body}

    

Example: Creating Thread with Lambda 

package com.vasanth.java8;
public class ThreadWithLambda {
    public static void main (String args[]){
        //Traditional approach
        Runnable r1=new Runnable() {
            @Override
            public void run() {
                System.out.println("Thread 1 started");
            }
        };
        Thread t1=new Thread(r1);
        t1.start();

                              //With Lambda

        Runnable r2=()->{
            System.out.println("Thread 2 started");
        };
        Thread t2=new Thread(r2);
        t2.start();
    }
}


Result: 

Thread 1 started

Thread 2 started


2. Functional Interface

 An interface with only single abstract method is called functional interface.

The functional interface should have Only one abstract method. Along with the one abstract method, they can have any number of default and static methods.

3. Method as reference

Each time when you are using lambda expression to just referring a method, you can replace your lambda expression with method reference

f your lambda expression is like this:

str -> System.out.println(str)

then you can replace it with a method reference like this:

System.out::println

The :: operator is used in method reference to separate the class or object from the method name.

4. Stream

Java provides a new additional package in Java 8 called java.util.stream. This package consists of classes, interfaces and enum to allows functional-style operations on the elements.

- Stream does not store the elements. it simply performs the aggregate operations(such as filter() and count() and etc) to get the desired stream of data.

- The aggregate operations that we perform on the collection, array or any other data source do not change the data of the source, they simply return a new stream. 

- All the stream operations are lazy in nature which means they are not executed until they are needed.

Example for Stream Filter (StreamFilter.java):

package com.vasanth.java8;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;

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

        List<product> products=new ArrayList<product>();
        products.add(new product(1,"Redmi note 7", 14000));
        products.add(new product(1,"Samsung s9", 18000));
        products.add(new product(1,"Iphone 10s", 25000));
        products.add(new product(1,"Oppo", 12000));

        //Filter
        Stream<product> filteredProduct=products.stream().filter(p->p.price>12000);
        filteredProduct.forEach(p->{
            System.out.println("name"+ p.name +"-> price :"+p.price);
        });

        //convert to List
        List<String> pro=products.stream().filter(p->p.price>12000).map(p->p.name).collect(Collectors.toList());
        pro.forEach(p->System.out.println(p));

        //convert to set
        Set<Double> price=products.stream().filter(p->p.price>12000).map(p->p.price).collect(Collectors.toSet());
        price.forEach(p->System.out.println(p));

        //Convert to map
        Map<String,Double> productMap=products.stream().collect(Collectors.toMap(p->p.name, p->p.price));
        System.out.println("productMap : "+productMap);
    }
}

class product{
    int id;
    String name;
    double price;

    public product(int id,String name,double price){
        this.id=id;
        this.name=name;
        this.price=price;

    }

}  

Result :

nameRedmi note 7-> price :14000.0
nameSamsung s9-> price :18000.0
nameIphone 10s-> price :25000.0
Redmi note 7
Samsung s9
Iphone 10s
18000.0
25000.0
14000.0

productMap : {Samsung s9=18000.0, Redmi note 7=14000.0, Oppo=12000.0, Iphone 10s=25000.0} 

5. Optional Class

This class is introduced to avoid NullPointerException that we frequently encounters if we do not perform null checks in our code. Using this class we can easily check whether a variable has null value or not and by doing this we can avoid the NullPointerException.

        Sample code:

package com.vasanth.java8;

import java.util.Optional;
public class OptionalClassExample {
    public static void main(String args[]){
        String[] names=new String[10];
        Optional<String> checkNull=Optional.ofNullable(names[5]);
        if(checkNull.isPresent()) {
            String lowerString = names[5].toLowerCase();
            System.out.println("lowerString : "+lowerString);
        }else{
            System.out.println("Value is not present");
        }
    }
}

6. Parallel Sort

The parallelSort() method uses the concept of multithreading which makes it much faster compared to the normal sort when there are lot of elements.

Algorithm of parallel sorting:

1. The given array is divided into the sub arrays and the sub arrays are further divided into the their sub arrays, this happens until the sub array reaches a minimum granularity.

2. The sub arrays are sorted individually by multiple threads. The parallel sort uses Fork/Join Framework for sorting sub arrays parallelly.

3. The sorted sub arrays are merged.

Sample code:

package com.vasanth.java8;
import java.util.Arrays;
public class Parallelsort {
    public static void main(String args[]){
        int[] numbers={4,7,2,10,5,0,1};
        printNumbers(numbers);
        //Arrays.sort(numbers);
        Arrays.parallelSort(numbers);
        printNumbers(numbers);
    }
    public static void printNumbers(int[] numbers){
        System.out.println("===============");
        for(int number:numbers) {
            System.out.println("numbers : " + number);
        }
    }
} 

    Result:

===============
numbers : 4
numbers : 7
numbers : 2
numbers : 10
numbers : 5
numbers : 0
numbers : 1
===============
numbers : 0
numbers : 1
numbers : 2
numbers : 4
numbers : 5
numbers : 7
numbers : 10 

7.String Joiner

A new class StringJoiner is introduced in the java.util package. Using this class we can join more than one strings with the specified delimiter, we can also provide prefix and suffix to the final string while joining multiple strings.

Sample Code: 

package com.vasanth.java8;

import java.util.StringJoiner;
public class StringJoinerExample {
    public static void main(String args[]){
        //Joiner
        StringJoiner joiner=new StringJoiner(",");
        joiner.add("Vasanth");
        joiner.add("Vasanth-3");
        joiner.add("Vasanth-2");
        System.out.println("Result : "+joiner); 
        //Joiner with prefix & suffix
        StringJoiner joiner1=new StringJoiner(",","[","]");
        joiner1.add("Vasanth");
        joiner1.add("Vasanth-3");
        joiner1.add("Vasanth-2");
        System.out.println("Joiner with prefix & suffix : "+joiner1);
    }
}

    Result:

 Result : Vasanth,Vasanth-3,Vasanth-2

Joiner with prefix & suffix : [Vasanth,Vasanth-3,Vasanth-2]

 

8.forEach

    A newly introduced forEach method to iterate over collections and Streams in Java


Example: 

package com.vasanth.java8;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ForEach {

public static void main (String args[]){

List<String> list1=new ArrayList<String>();
list1.add("Vasanth");
list1.add("Vasanth-3");
list1.add("Vasanth-2");
list1.add("Vasanth-4");

//Iterate List
//list1.forEach(System.out::println); //Passing method as reference
list1.forEach(l1->System.out.println(l1));

//Iterate Map
Map<Integer,String> emp=new HashMap<Integer, String>();
emp.put(111,"Vasanth");
emp.put(222,"xxxx");
emp.put(333,"Vasanth-2");
emp.put(444,"Test");

//forEach with collection
emp.forEach((key,value)->{
System.out.println("emp-id:"+ key +" , Name:"+value);
if(value.equals("Vasanth")){
System.out.println("Employee match found : " + value);
}
});

//forEach ordered with stream
System.out.println("Employee name starts with V :");
emp.values().stream().filter(name->name.startsWith("V")).forEachOrdered(name->System.out.println(name));

}
}

Result:
Vasanth
Vasanth-3
Vasanth-2
Vasanth-4
emp-id:444 , Name:Test
emp-id:333 , Name:Vasanth-2
emp-id:222 , Name:xxxx
emp-id:111 , Name:Vasanth
Employee match found : Vasanth
Employee name starts with V :
Vasanth-2
Vasanth



Comments

Popular posts from this blog

Java Design Patterns