Java 8 Features with Examples

Here we will see Java 8 features in details.

Lambda expressions – It is an anonymous function which doesn’t have a name, access modifier and return type. .

Syntax –

(lambda-arguments) -> {lambda body}
  • (lambda-arguments)  – we can have one or multiple arguments or it can be empty.
  • ->(arrow) –     This  links (lambda-arguments) and {body}.
  • {lambda body}          – Here we have core logic.

Benefits of lambda expression –

  • Lambda expression allows us to use functional programming than object-oriented programming.
  • With help of lambda expression, we can reduce the code.
  • It supports parallel processing.
  • We can use predefined API and library in an easier way.

[stextbox id=’info’]

Note –

  • If we have only one line or statement in body curly braces are optional.
  • (lambda-arguments) – It can have any number of arguments.
  • If we use return keyword, curly braces are mandatory.
  • To call lambda expression we must use Functional interface(contains single abstract method ).
  • Functional interface can contain a single abstract method and any number of static or default method(these methods as we must have a body as we can have method body in the interface, Java 8 onwards).
  • Runnable and Comparable are interfaces are examples of the Functional interface.
  • We use @FunctionalInterface annotation to define a functional interface, although this is optional.

[/stextbox]

Let’s see a couple of examples related to the lambda expression.  All examples will be in both, earlier Java 8 and in Java 8.

  • Example 1 – Printing hello world using a lambda expression.

Without using lambda expression –

interface I2 {
	public void m1();

}

public class HelloWorld implements I2 {
	@Override
	public void m1() {
		System.out.println("hello world");
	}

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

Output is – hello world

Using lambda expression –

@FunctionalInterface
interface I1 {
	public void m1();

}

public class LambdaExample {

	public static void main(String[] args) {
		I1 i1 = () -> System.out.println("hello world");
		i1.m1();
	}
}

Output is – hello world

In the above program, @FunctionalInterface is optional. But this annotation provides compile time safety if something goes wrong it will tell us. Even below code will work fine.

interface I1 {
	public void m1();

}

public class LambdaExample {

	public static void main(String[] args) {
		I1 i1 = () -> System.out.println("hello world");
		i1.m1();
	}
}

Output is – hello world

  • Example 2 – square of the number. Here we will have one parameter in the lambda expression

Without using lambda expression –

interface i5 {
	public int squreOfNumber(int i);

}

public class SqureOfNumber implements i5 {
	@Override
	public int squreOfNumber(int i) {
		return i * i;

	}

	public static void main(String[] args) {
		SqureOfNumber number = new SqureOfNumber();
		System.out.println(number.squreOfNumber(10));
	}
}

Output is – 100

Using lambda expression – square of two numbers

interface I6 {
	public int squreOfNumber(int i);

}

public class SqureOfNoUsingLambda {
	public static void main(String[] args) {
		I6 i6 = (i) -> i * i;
		System.out.println(i6.squreOfNumber(10));
	}
}
  • Example 3 – sum of two number. Here we will see program having two parameters in the lambda expression.

Without using lambda expression –

interface I4 {
	public void sumOfTwoNumber(int n1, int n2);

}

public class SumOfTwoNumWithoutLambda implements I4 {
	@Override
	public void sumOfTwoNumber(int n1, int n2) {
		System.out.println("Sum of n1 and n2 is:-   " + (n1 + n2));
	}

	public static void main(String[] args) {
		SumOfTwoNumWithoutLambda withoutLambda = new SumOfTwoNumWithoutLambda();
		withoutLambda.sumOfTwoNumber(20, 30);
	}
}

Output is – Sum of n1 and n2 is:- 50

Using lambda expression –

@FunctionalInterface
interface I3 {
	public void sumOfTwoNumber(int n1, int n2);

}

public class LambdaExample2 {
	public static void main(String[] args) {
		I3 i3 = (n1, n2) -> System.out.println("Sum of n1 and n2 is:-   "+ (n1 + n2));
		i3.sumOfTwoNumber(20, 30);
	}
}

Output is – Sum of n1 and n2 is:- 50

  • Example 4 – In this example, we will see how to write return statement in the lambda expression.
@FunctionalInterface
interface I6 {

	public int m1(int i);

}

public class SqureOfNoUsingLambda {
	public static void main(String[] args) {
		I6 i6 = (i) -> {
			return i * i;
		};
		System.out.println(i6.m1(10));
	}
}

Output is – 100

Example 5 –

interface I1 {
	public void m1();

}

class Test implements I1 {

	@Override
	public void m1() {
		System.out.println("hello world");

	}

}

public class LambdaExample {

	public static void main(String[] args) {

		I1 i1 = new Test();
		i1.m1();

		I1 i11 = () -> System.out.println("hello world");
		i11.m1();

		// what is difference to create references i1 and i11?
	}
}

Output is –

hello world
hello world

In the above program, what is the difference create references i1 and i11? In the case of line 20 Test class is implementing the I1 interface whereas line 23 we are creating a functional interface. Here i1 is a reference of I1 and object of Test class whereas i11 is a lambda expression type of I1.

Example 6 – Defining Functional interface as an inner class.

public class FunctionalInterfASInnerClass {

	// inner class
	interface InnerInterface {
		public void m1(int a, int b);
	}

	// inner class
	interface InnerInterface2 {
		public void m2(String str);
	}

	public static void main(String[] args) {
		InnerInterface innerInterface1 = (a, b) -> System.out.println(a * b);
		innerInterface1.m1(20, 30);

		InnerInterface2 innerInterface = (String str) -> System.out.println(str
				.toUpperCase());
		innerInterface.m2("ram");

	}
}

Output is –

600
RAM

Example 7 – 

class NormalExample implements Runnable {

	@Override
	public void run() {
		for (int i = 0; i < 5; i++) {
			System.out.println("without lambda expression  " + i);
		}

	}

}

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

		NormalExample example = new NormalExample();
		Thread thread1 = new Thread(example);
		thread1.start();

		// here we are going to perform same operation using lambda
		Runnable runnable = () -> {
			for (int i = 0; i < 5; i++) {
				System.out.println("with lambda expression     " + i);
			}
		};
		Thread thread = new Thread(runnable);
		thread.start();
	}
}

Output is –

without lambda expression 0
without lambda expression 1
without lambda expression 2
without lambda expression 3
without lambda expression 4
with lambda expression 0
with lambda expression 1
with lambda expression 2
with lambda expression 3
with lambda expression 4

Example 8 – 

interface I11 {
	public boolean returnName(String name1);
}

class Employee {
	String empName = "ram";

	public String getEmpName() {
		return empName;
	}

}

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

		Employee e1 = new Employee();
		I11 i11 = (name1) -> name1.equals(e1.getEmpName());

		System.out.println(i11.returnName("ram"));

	}
}

Output is – true

Example 9 – 

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

public class IteratingLlistUsingLambda {
	public static void main(String[] args) {
		List<String> arrayListObj = new ArrayList<String>();
		arrayListObj.add("ram");
		arrayListObj.add("mohan");
		arrayListObj.add("sohan");

		// Using enhanced for loop
		for (String strObj : arrayListObj) {
			System.out.println("Using enhanced for loop  " + strObj);
		}

		// Using java 8 lambda
		arrayListObj.forEach((str) -> System.out
				.println("Using lambda expression  " + str));
	}
}

Output is –

Using enhanced for loop ram
Using enhanced for loop mohan
Using enhanced for loop sohan
Using lambda expression ram
Using lambda expression mohan
Using lambda expression sohan

Example 10 – 

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

class Book {
	int bookId;
	String bookName;

	public Book(int bookId, String bookName) {
		this.bookId = bookId;
		this.bookName = bookName;
	}

}

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

		// creating a list type of book
		List<Book> listOfBook = new ArrayList<Book>();

		// creating Book object using argumented constructor
		Book b1 = new Book(2, "five point someone");
		Book b2 = new Book(4, "godan");
		Book b3 = new Book(6, "devdash");
		Book b4 = new Book(1, "lolita");

		// adding book into list
		listOfBook.add(b1);
		listOfBook.add(b2);
		listOfBook.add(b3);
		listOfBook.add(b4);

		// sorting book object on basis of name
		System.out.println("Sorting book object on basis of name");
		Collections.sort(listOfBook, (book1, book2) -> {
			return book1.bookName.compareTo(book2.bookName);
		});

		// iterating using for-each loop
		for (Book book : listOfBook) {
			System.out.println("bookId is  " + book.bookId + " "
					+ "bookName is  " + book.bookName);

		}

		// sorting book object on basis of id
		System.out.println("sorting book object on basis of id");
		Collections.sort(listOfBook, (book1, book2) -> {
			
			return book1.bookId - book2.bookId;
		});

		// iterating using for-each loop
		for (Book book : listOfBook) {
			System.out.println("bookId is  " + book.bookId + " "
					+ "bookName is  " + book.bookName);

		}

	}
}

Output –

Sorting book object on basis of name
bookId is 6 bookName is devdash
bookId is 2 bookName is five point someone
bookId is 4 bookName is godan
bookId is 1 bookName is lolita
sorting book object on basis of id
bookId is 1 bookName is lolita
bookId is 2 bookName is five point someone
bookId is 4 bookName is godan
bookId is 6 bookName is devdash

Example 11 – 

package lambdaexample;



public class LambdaExample11 {
	
	public static void m1() {
		for(int i = 0; i<5; i++) {
			System.out.println("value of i is "+i);
		}
		
	}
public static void main(String[] args) {
	
	Thread thread = new Thread(() -> m1());
	thread.start();
		
	
}
}

Output is –

value of i is 0
value of i is 1
value of i is 2
value of i is 3
value of i is 4

Example 12 – 

package lambdaexample;

import java.util.HashMap;
import java.util.Map;
 
public class LambdaExample12 {
	public static void main(String[] args) {
		Map<Integer, String> hashMapObj = new HashMap<>();
 
		hashMapObj.put(2, "ram");
		hashMapObj.put(5, "mohan");
		hashMapObj.put(3, "sohan");
		hashMapObj.put(9, "rohit");
 
		hashMapObj.forEach((key, value) -> {
			System.out.println("Key is : " + key + "   Value is : " + value);
		});
 
	}
}

Output is –

Key is : 2 Value is : ram
Key is : 3 Value is : sohan
Key is : 5 Value is : mohan
Key is : 9 Value is : rohit