Skip to main content

Command Palette

Search for a command to run...

Java Lambda Expression

Updated
6 min read

What is a Lambda?

A lambda expression is an anonymous function

  • A function without name

  • Without access modifier

  • Without return type

Lambda provides a clear and concise way to implement functional interface(interface with exactly one abstract method.)

Note: Lambda expression is specific to Functional interface only without it we can't write lambda expressions.

A lambda expression is NOT an object - it is an instance of a functional interface. The JVM uses invoke dynamic to implement lambdas efficiently(no new class file per lambda).

Lambda Syntax & Examples

Form Syntax
No params () -> expression
Single param x -> expression
Single param types (Type x) -> expression
Multiple Params (x,y) -> expression
Block params (x)-> {statement;return x;}
void block (x)-> {statement;}

Learn to write your first lambda expression

Generally, we write method in java like below

public void methodName(){
    System.out.println("first lambda expression");
}

for lambda expression, we don't need method name, access modifier and return type, so it will look like below

() -> {
            System.out.println("first lambda expression");
    }

for single statement, no curly braces required.

() -> System.out.println("first lambda expression");

complete code of no param

@java.lang.FunctionalInterface
interface FunctionalInterface{
    void methodName();
}
public class LambdaExpression {
    public static void main(String[] args) {
        FunctionalInterface i = ()-> System.out.println("first lambda expression");
        i.methodName();
    }
}

single param

@java.lang.FunctionalInterface
interface FunctionalInterface{
    int square(int num);
}
public class LambdaExpression {
    public static void main(String[] args) {
        FunctionalInterface i = x -> x * x;
        System.out.println(i.square(10));
    }
}

single param typed

@java.lang.FunctionalInterface
interface FunctionalInterface{
    int lengthOfString(String s);
}
public class LambdaExpression {
    public static void main(String[] args) {
        FunctionalInterface i = (String s) -> s.length();
        System.out.println(i.lengthOfString("amol"));
    }
}

multiple params

@java.lang.FunctionalInterface
interface FunctionalInterface{
    int sum(int num1, int num2);
}
public class LambdaExpression {
    public static void main(String[] args) {
        FunctionalInterface i = (x,y) -> x + y;
        System.out.println(i.sum(10,20));
    }
}

block body

@java.lang.FunctionalInterface
interface FunctionalInterface{
    int sum(int num1, int num2);
}
public class LambdaExpression {
    public static void main(String[] args) {
        FunctionalInterface i = (x,y) -> {
            System.out.println("side effect");
            return x + y;
        };
        System.out.println(i.sum(10,20));
    }
}

void block

@java.lang.FunctionalInterface
interface FunctionalInterface{
    void printMessage();
}
public class LambdaExpression {
    public static void main(String[] args) {
        FunctionalInterface i = () -> {
            System.out.println("side effect");
        };
        i.printMessage();
    }
}

Identify valid/invalid lambda expression

n -> return n*n;//invalid- missing curly braces

n-> {return n*n;};//valid

n-> {return n*n};//invalid, missing semi-colon after return expression

n->{n*n;};//invalid, missing return keyword

n-> n*n;//valid-  valid way of using 

Lambda expression with Multi-threading

public class LambdaWithMultithreading {
    public static void main(String[] args) {
        Runnable r =  () -> {
          for (int i=0;i<5;i++){
              System.out.println("child thread..");
          }
        };
        Thread t = new Thread(r);
        t.start();
    }
}

output

child thread..
child thread..
child thread..
child thread..
child thread..

Comparator demo without lambda

import java.util.*;
import java.util.Comparator;

public class ComparatorWithoutLambda implements Comparator<Integer> {
    @Override
    public int compare(Integer n1, Integer n2) {
        return n1 > n2 ? -1: n1 < n2? 1:0;
    }
    public static void main(String[] args) {
        List<Integer> l = Arrays.asList(2,1,3,4);
//        Collections.sort(l); // follows default sorting order
//        System.out.println(l);

        Collections.sort(l,new ComparatorWithoutLambda());
        System.out.println(l);
    }
}

output

[4, 3, 2, 1]

Comparator with lambda expression

public class ComparatorWithLambda {

    public static void main(String[] args) {
        List<Integer> l = Arrays.asList(2,1,3,4,6,5);

        Comparator<Integer> c = (n1,n2) -> n1 > n2?-1:n1 < n2 ? 1:0;
        Collections.sort(l,c);
        System.out.println(l);
    }
}

output

[6, 5, 4, 3, 2, 1]

Comparator demo with lambda expression for custom object

import java.util.*;
class Student{
    int sid;
    String stdName;

    public Student(int id, String name){
        this.sid = id;
        this.stdName = name;
    }
    public String toString(){
        return this.sid+" - "+this.stdName;
    }
}
public class LambdaWithCustomObject {

    public static void main(String[] args) {
        List<Student> stdList = Arrays.asList(new Student(103,"amol"),new Student(101,"sagar"),
                new Student(102, "prashant"),new Student(104,"arjun"));

        System.out.println(stdList);

        /*
            reverse sorting based on student id
         */
        Comparator<Student> s = (s1,s2)-> Integer.compare(s1.sid, s2.sid);
        Collections.sort(stdList,s);
        System.out.println("sorting based on id: "+stdList);

        /*
        reverse sorting based on student name
         */
        Comparator<Student> sname = (s1,s2) -> s2.stdName.compareTo(s1.stdName);
        Collections.sort(stdList,sname);
        System.out.println("sorting based on name"+ stdList);
    }
}

output

[103 - amol, 101 - sagar, 102 - prashant, 104 - arjun]
sorting based on id: [101 - sagar, 102 - prashant, 103 - amol, 104 - arjun]
sorting based on name[101 - sagar, 102 - prashant, 104 - arjun, 103 - amol]

Anonymous Inner class vs Lambda Expression

We are writing a class which is extending to the thread class.

Note - This doesn't have any name, called anonymous class

Thread t=new Thread{
   public void run(){

  }
// t is the object of child class of Thread
};

Now, we will create a anonymous class which will implement the Runnable interface.

Runnable r=new Runnable(){
   public void run(){

  }
//r is the object of class which is implementating Runnable interface.
};
  • Anonymous inner class is not equivalent to the lambda expression.

  • If anonymous inner class implements a interface which contains single abstract method then only we can replace that anonymous inner class with lambda expression.

  • Anonymous inner class can extend normal class.

  • Anonymous inner class can extend abstract class

  • Anonymous Inner class can implement interface, which might contain any number of abstract methods.

  • Lambda expression can implement interface which contains a single abstract method.

Variable Capture(closure)

Lambdas can capture variables from their enclosing scope, but ONLY if those variables are effective final(value never changed after initialization)

public class EffectiveFinalDemo {
    public static void main(String[] args) {
        int base = 30;
        Function<Integer, Integer> f = x -> x + base; //valid
        System.out.println(f.apply(20));
       // base = 100; // Invalid - compile error - Variable used in lambda expression should be final or effectively final

    }
}

output

50