Lambda expressions are anonymous methods i.e. methods with no name. It allows developers to shorten the code and make it more readable.

Before learning how to implement lambda in Java, first we need to see following type of interfaces:

Marker Interface

A marker interface is an interface with no methods. It is used to notify the environment that a class have implemented that interface.

Example:  Serializable

If you want to serialize a class objects, you must implement the Serializable interface.

Functional Interface

A functional interface has one method declaration only.

Example:  Runnable

To implement multi-threading, a class needs to implement the Runnable interface and provide the definition for the method run().

Lambda Expression Syntax

A lambda expression is declared with following syntax:

InterfaceName referenceName = ( parameter1, parameter2.. ) -> statement
InterfaceName referenceName = ( parameter1, parameter2.. ) -> { statements... }

To execute a lambda expression, write:

referenceName.methodName( argument1, argument2.. );

*Note: Lambda’s work only with functional interfaces.

Here is an example:

public class Test {
   public static void main(String[] args) {
      Data d = (str) -> System.out.println(str);
      d.show("Hello");
   }
}

interface Data{
   void show(String str);
}

Here is another example:

public class Test {
   public static void main(String[] args) {
      Calculator add = (a,b) -> System.out.println(a+b);
      Calculator subtract = (a,b) -> System.out.println(a-b);
      Calculator multiply = (a,b) -> System.out.println(a*b);
      Calculator divide = (a,b) -> System.out.println(a/b);

      add.operate(5, 6);
      subtract.operate(5, 6);
      multiply.operate(5, 6);
      divide.operate(5, 6);
   }
}

interface Calculator{
 void operate(double a, double b);
}

The following example uses a separate class that receives a lambda expression in constructor.

public class Test {
   public static void main(String[] args) {
      new Data( (a,b) -> System.out.println(a+b), 10, 30);
      new Data( (a,b) -> System.out.println(a*b), 10, 30);
 }
}
class Data{
   public Data(Calculator calculate, double a, double b){
      calculate.operate(a, b); 
   }
}
interface Calculator{
   void operate(double a, double b);
}

Modifying existing codes

1. Threads

Previously we start a thread anonymously like this:

 Runnable r = new Runnable() {
 
    @Override
    public void run() {
       System.out.println("Hello from thread");
    }
 };
 new Thread(r).start();

Since, Runnable is a functional interface, we can write the above code like this:

new Thread( () -> System.out.println("Hello from thread") ).start();

2. Events

Previously we define our events like this:

btn.addActionListener(new ActionListener() {
   @Override
   public void actionPerformed(ActionEvent e) {
       System.out.println("You clicked me");
   }
}).start();

Since ActionListener is a functional interface, we can write the above code like this:

btn.addActionListener( (e) -> { System.out.println("You clicked me") });

3. List sorting

Previously we use to sort our lists like this:

 List<Integer> numbers = new ArrayList<Integer>();
 
 numbers.add(40);
 numbers.add(20);
 numbers.add(50);
 numbers.add(10);
 numbers.add(30);
 
 Comparator<Integer> comparator = new Comparator<Integer>() { 
    @Override
    public int compare(Integer a, Integer b) {
       return a-b;
    }
 };
 
 Collections.sort(numbers, comparator);
 
 for(Integer x : numbers)
    System.out.println(x);

Since Comparator is a functional interface, we can write the above code like this:

List<Integer> numbers = new ArrayList<Integer>();
 
 numbers.add(40);
 numbers.add(20);
 numbers.add(50);
 numbers.add(10);
 numbers.add(30);
 
 Collections.sort(numbers, (a,b) -> a-b);      // b-a for reverse sorting
 
 for(Integer x : numbers)
    System.out.println(x);

4. List traversal

Previously we use to sort our lists like this:

 List<Integer> numbers = new ArrayList<Integer>();
 
 numbers.add(40);
 numbers.add(20);
 numbers.add(50);
 numbers.add(10);
 numbers.add(30);
 
 for(Integer x : numbers)
    System.out.println(x);

We can now write the above code like this:

 List<Integer> numbers = new ArrayList<Integer>();
 
 numbers.add(40);
 numbers.add(20);
 numbers.add(50);
 numbers.add(10);
 numbers.add(30);
 
 numbers.forEach(x -> System.out.println(x) );