Java 8 Lambda Expressions


1. Overview

In this post, we will discuss the most important feature of Java 8 that is Lambda Expressions. We will learn Lambda Expressions with lots of examples.
You can download the source code from my GitHub Repository
  • Lambda Expression facilitates functional programming and simplifies the development a lot.
  • It provides a clear and concise way to represent one method interface using an expression. It is very useful in the collection library. It helps to iterate, filter, and extract data from the collection.
  • The Lambda expression is used to provide the implementation of an interface that has a functional interface. It saves a lot of code. In the case of the lambda expression, we don't need to define the method again for providing the implementation. Here, we just write the implementation code.
  • Java lambda expression is treated as a function, so the compiler does not create a .class file.

Functional Interface

Lambda expression provides an implementation of the Java 8 Functional Interface. An interface that has only one abstract method is called a functional interface. 
Java provides an annotation @FunctionalInterface, which is used to declare an interface as a functional interface.
If you have used Runnable, Callable, Comparator, FileFilter, PathMatcher, EventHandler interfaces in your projects then you can replace its implementation with Lambda Expression.
We have a separate post for Functional Interface in detail - Java 8 Functional Interface.

2. Why use Lambda Expression

  • To provide the implementation of the Java 8 Functional Interface.
  • Less coding.
  • Lambda Expressions enable you to encapsulate a single unit of behavior and pass it to other code. You can use lambda expressions if you want a certain action performed on each element of a collection, when a process is completed, or when a process encounters an error.

3. Java 8 Lambda Expressions

Java Lambda Expression Syntax
(argument-list) -> {body}  
Java lambda expression consists of three components.
  1. Argument-list: It can be empty or non-empty as well.
  2. Arrow-token: It is used to link arguments-list and body of expression.
  3. Body: It contains expressions and statements for the lambda expression.
The below diagram shows a few simple lambda expression examples:

Java Lambda Expressions Examples

1. Java Simple Lambda Expression Example

Here, we are implementing a Drawable functional interface method using the lambda expression:
interface Drawable{  
    public void draw();  
}  
public class LambdaExpressionExample {  
    public static void main(String[] args) {  
        int width=10;         
        //with lambda 
        Drawable withLambda=()->{  
            System.out.println("Drawing "+width);  
        };  
        withLambda.draw();  
    }  
} 
Output :
Drawing 10

2. Java Lambda Expression Example: No Parameter

Please refer to the comments in the code, which indicates that code with Lambda expression and without Lambda expression.
interface Sayable {
    public String say();
}
public class JLEExampleNoParameter {
    public static void main(String[] args) {
        // without lambda expression
        Sayable sayable = new Sayable() {
            @Override
            public String say() {
                return "Return something ..";
            }
        };
        sayable.say();

        // with lambda expression
        Sayable withLambda = () -> {
            return "Return something ..";
        };
        withLambda.say();
    }
}

3. Java Lambda Expression Example: Single Parameter

Please refer to the comments in the code, which indicates that code with Lambda expression and without Lambda expression.
interface Printable {
    void print(String msg);
}

public class JLEExampleSingleParameter {

    public static void main(String[] args) {
     // without lambda expression
         Printable printable = new Printable() {
            @Override
            public void print(String msg) {
               System.out.println(msg);
            }
         };
         printable.print(" Print message to console....");
  
         // with lambda expression
         Printable withLambda = (msg) -> System.out.println(msg);
         withLambda.print(" Print message to console....");
     }
}
Output :
 Print message to console....
 Print message to console....

 4. Java Lambda Expression Example: Multiple Parameters

Please refer to the comments in the code, which indicates that code with Lambda expression and without Lambda expression.
interface Addable{  
    int add(int a,int b);  
}  
public class JLEExampleMultipleParameters {

 public static void main(String[] args) {
  
     // without lambda expression
  Addable addable = new Addable() {
   @Override
   public int add(int a, int b) {
    return a + b;
   }
  };
  addable.add(10, 20);
  
  // with lambda expression
   // Multiple parameters in lambda expression  
        Addable withLambda = (a,b)->(a+b);  
        System.out.println(withLambda.add(10,20));  
          
        // Multiple parameters with data type in lambda expression  
        Addable withLambdaD = (int a,int b) -> (a+b);  
        System.out.println(withLambdaD.add(100,200));  
 }
 
}

5. Java Lambda Expression Example: Multiple Statements

interface IAvarage{  
    double avg(int[] array);  
}  
public class JLEExampleMultipleStatements {

    public static void main(String[] args) {
  
        // without lambda expression, IAvarage implementation using anonymous class  
         IAvarage avarage = new IAvarage() {
            @Override
            public double avg(int[] array) {
                double sum = 0;
                int arraySize = array.length;
    
                System.out.println("arraySize : " + arraySize);
                for (int i = 0; i < array.length; i++) {
                    sum = sum + array[i]; 
                } 
                System.out.println("sum : " + sum);
    
                return (sum/ arraySize);
           }
        };
        int[] array = {1,4,6,8,9};
        System.out.println(avarage.avg(array));
  
        // with a lambda expression
        // You can pass multiple statements in lambda expression 
  
        IAvarage withLambda = (withLambdaArray) -> {
            double sum = 0;
            int arraySize = withLambdaArray.length;
   
            System.out.println("arraySize : " + arraySize);
            for (int i = 0; i < withLambdaArray.length; i++) {
                sum = sum + withLambdaArray[i]; 
            }
            System.out.println("sum : " + sum);
   
            return (sum/ arraySize);
       };
  
        int[] withLambdaArray = {1,4,6,8,9};
        System.out.println(withLambda.avg(withLambdaArray)); 
    }
}

6. Java Lambda Expression Example: Creating Thread

public class JLEExampleRunnable {

    public static void main(String[] args) {
  
    //without lambda, Runnable implementation using anonymous class  
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            System.out.println(" Runnable example without lambda exp.");
        }
    };
    Thread thread = new Thread(runnable);
    thread.start();
  
     //with lambda 
    Runnable withLambda = () -> System.out.println(" Runnable example with lambda exp.");
    Thread thread1 = new Thread(withLambda);
    thread1.start();
  }
}
Output :
 Runnable example without lambda exp.
 Runnable example with lambda exp.

7. Java Lambda Expression Example: Comparator

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

public class JLEComparatorExample {

    public static void main(String[] args) {

        List<Person> listOfPerson = new ArrayList<Person>();
        listOfPerson.add(new Person("abc", 27));
        listOfPerson.add(new Person("mno", 26));
        listOfPerson.add(new Person("pqr", 28));
        listOfPerson.add(new Person("xyz", 27));

        // Without lambda expression.
        // Sort list by age
        Comparator<Person> comparator = new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getAge() - o2.getAge();
            }
        };

        Collections.sort(listOfPerson, comparator);

        System.out.println(" sort persons by age in ascending order");
        for (Person person : listOfPerson) {
            System.out.println(" Person name : " + person.getName());
        }

        // Witht lambda expression.
        // Sort list by age

        Collections.sort(listOfPerson, (Person o1, Person o2) -> {
            return o1.getAge() - o2.getAge();
        });
        // Use forEach method added in java 8
        System.out.println(" sort persons by age in ascending order");
        listOfPerson.forEach(
           (person) -> System.out.println(" Person name : " + person.getName()));
        }
  }

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
       super();
       this.name = name;
       this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

8. Java Lambda Expression Example: Event Listener

import javax.swing.JButton;  
import javax.swing.JFrame;  
import javax.swing.JTextField;  
public class LambdaEventListenerExample {  
    public static void main(String[] args) {  
        JTextField tf=new JTextField();  
        tf.setBounds(50, 50,150,20);  
        JButton b=new JButton("click");  
        b.setBounds(80,100,70,30);  
        // lambda expression implementing here.  
        b.addActionListener(e-> {tf.setText("hello swing");});  
        JFrame f=new JFrame();  
        f.add(tf);f.add(b);  
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
        f.setLayout(null);  
        f.setSize(300, 200);  
        f.setVisible(true);  
    }  
} 

9. Iterate ArrayList with forEach() method + Lambda Expression Example

package net.javaguides.collections;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
 * 
 * Java program to demonstrate different ways to Iterate over an ArrayList in Java
 * @author Ramesh Fadatare
 *
 */
public class DifferentWaysListIterateProgram {

    public static void main(String...args) {

        List < String > courses = Arrays.asList("C", "C++", "Core Java", "J2EE", "Spring", "Hibernate", "Python");

   
        // JDK 8 streaming example lambda expression
        courses.stream().forEach(course -> printCourse(course));

        // JDK 8 streaming example method reference
        courses.stream().forEach(DifferentWaysListIterateProgram::printCourse);

        // JDK 8 for each with lambda
        courses.forEach(course -> printCourse(course));

        // JDK 8 for each
        courses.forEach(DifferentWaysListIterateProgram::printCourse);
    }

    // common method to print course
    private static void printCourse(String course) {
        System.out.println("course name :: " + course);
    }
}

10. Iterate HashSet with forEach() method + Lambda Expression Example

package net.javaguides.collections;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
 * Java program to demonstrate different ways to iterate over a Set in Java
 * 
 * @author Ramesh Fadatare
 *
 */
public class DifferentWaysSetIterateProgram {

    public static void main(String...args) {

        Set < String > courses = new HashSet < String > ();
        courses.add("Java");
        courses.add("C");
        courses.add("C++");
        courses.add("Python");
        courses.add("Scala");

        // JDK 8 streaming example lambda expression
        courses.stream().forEach(course -> coursePrinter(course));

        // JDK 8 streaming example method reference
        courses.stream().forEach(DifferentWaysSetIterateProgram::coursePrinter);

        // JDK 8 for each with lambda
        courses.forEach(course -> coursePrinter(course));

        // JDK 8 for each
        courses.forEach(DifferentWaysSetIterateProgram::coursePrinter);
    }

    // common method to print course
    private static void coursePrinter(String course) {
        System.out.println("course name :: " + course);
    }
}

11. Iterate HashMap with forEach() method + Lambda Expression Example

package net.javaguides.collections;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * This program demonstrate different ways to iterate over a Map in Java
 * 
 * @author Ramesh Fadatare
 *
 */
public class DifferentWaysMapIterateProgram {

    public static void main(String...args) {

        Map < Integer, String > coursesMap = new HashMap < Integer, String > ();
        coursesMap.put(1, "C");
        coursesMap.put(2, "C++");
        coursesMap.put(3, "Java");
        coursesMap.put(4, "J2EE");
        coursesMap.put(5, "Python");
        coursesMap.put(6, "Scala");

   
        // JDK 8 for each with lambda
        coursesMap.forEach((k, v) -> coursePrinter(k, v));

        // JDK 8 for each method reference
        coursesMap.forEach(DifferentWaysMapIterateProgram::coursePrinter);

    }

    // common method to print map key value
    private static void coursePrinter(Integer number, String brand) {
        System.out.println("course no : " + number + " and course name : " + brand);
    }
}

Summary

  • Lambda expressions have three parts: a list of parameters, and arrow, and a body: (Object o) -> System.out.println(o);
  • You can think of lambda expressions as anonymous methods (or functions) as they don't have a name.
  • A lambda expression can have zero (represented by empty parentheses), one or more parameters.
  • The type of the parameters can be declared explicitly, or it can be inferred from the context.
  • If there is a single parameter, the type is inferred and is not mandatory to use parentheses.
  • If the lambda expression uses as a parameter name that is the same as a variable name of the enclosing context, a compile error is generated.
  • If the body has one statement, curly brackets are not required, and the value of the expression (if any) is returned.
  • If the body has more than one statement, curly brackets are required, and if the expression returns a value, it must return with a return statement.
  • If the lambda expression doesn't return a result, a return statement is optional.
  • The signature of the abstract method of a functional interface provides the signature of a lambda expression.
  • In order to use a lambda expression, you first need a functional interface.
  • However, lambda expressions don't contain the information about which functional interfaces are implementing.
  • The type of the expression is deduced from the context in which the lambda is used. This type is called a target type.
  • The contexts where the target type of a lambda expression can be inferred include an assignment, method or constructor arguments, and a cast expression.
  • Default methods of a functional interface cannot be accessed from within lambda expressions.

Source code on GitHub

The source code of this post is available on GitHub Repository.

4. Related Java 8 Top Posts

  1. Java 8 Functional Interfaces
  2. Java 8 Method References
  3. Java 8 Stream API
  4. Java 8 Optional Class
  5. Java 8 Collectors Class
  6. Java 8 StringJoiner Class
  7. Java 8 Static and Default Methods in Interface
  8. Guide to Java 8 forEach Method
  9. Handle NullPointerException in Controller, Service, and DAO Layer using Java 8 Optional Class
  10. How to Use Java 8 Stream API in Java Projects
  11. Migrating Source Code to Java 8

Free Spring Boot Tutorial | Full In-depth Course | Learn Spring Boot in 10 Hours


Watch this course on YouTube at Spring Boot Tutorial | Fee 10 Hours Full Course