Fundamentals 15 min read

Master Java Lambda Expressions: From Basics to Advanced Usage

This article explains what Java lambda expressions are, why they were introduced, their syntax and classifications, functional interfaces, core functional interfaces, method references, and provides multiple code examples that progressively simplify traditional anonymous inner classes into concise lambda forms.

Architect's Must-Have
Architect's Must-Have
Architect's Must-Have
Master Java Lambda Expressions: From Basics to Advanced Usage

What is a Lambda Expression?

A lambda expression can be understood as an anonymous function that allows a function to be passed as a parameter, embodying functional programming by treating code as a first‑class value.

Why were Lambda Expressions introduced?

Java developers wanted the same concise functional capabilities found in languages like JavaScript and Python; Java 8 added lambda support to make code more efficient.

Lambda expressions make programming more efficient.

Example using a traditional inner class:

package com.isea.java;
public class TestLambda {
    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable());
        thread.start();
        thread.close();
    }
}
class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("Hello");
    }
}

Refactored with an anonymous inner class:

package com.isea.java;
public class TestLambda {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            // implementation
            @Override
            public void run() {
                System.out.println("Hello");
            }
        }).start();
    }
}

Further simplified using a lambda:

package com.isea.java;
public class TestLambda {
    public static void main(String[] args) {
        new Thread(() -> System.out.println("Hello")).start();
    }
}

Lambda Syntax

(Lambda parameter list) -> {Lambda body} Copy the parentheses, write the arrow, and place the logic inside braces. @FunctionalInterface default static method

Key points: the arrow separates parameters from implementation; parameters are listed in parentheses; the body is enclosed in braces.

Lambda Classifications

No parameters, no return value

package com.isea.java;
public class TestLambda {
    public static void main(String[] args) {
        new Thread(() -> System.out.println("Hello")).start();
    }
}

Parameters, no return value

package com.isea.java;
import java.util.ArrayList;
public class TestLambda {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("AAAAA");
        list.add("BBBBB");
        list.add("CCCCC");
        list.add("DDDDD");
        list.forEach(t -> System.out.print(t + "\t"));
    }
}

No parameters, return value

package com.isea.java;
import java.util.Random;
import java.util.stream.Stream;
public class TestLambda {
    public static void main(String[] args) {
        Random random = new Random();
        Stream<Integer> stream = Stream.generate(() -> random.nextInt(100));
        stream.forEach(t -> System.out.println(t));
    }
}

Parameters and return value

package com.isea.java;
import java.text.Collator;
import java.util.TreeSet;
public class TestLambda {
    public static void main(String[] args) {
        Collator collator = Collator.getInstance();
        TreeSet<Student> set = new TreeSet<>((s1, s2) -> collator.compare(s1.getName(), s2.getName()));
        set.add(new Student(10, "张飞"));
        set.add(new Student(3, "周瑜"));
        set.add(new Student(1, "宋江"));
        set.forEach(student -> System.out.println(student));
    }
}
class Student {
    private int id;
    private String name;
    public Student(int id, String name) { this.id = id; this.name = name; }
    public int getId() { return id; }
    public String getName() { return name; }
    @Override
    public String toString() {
        return "Student{id=" + id + ", name='" + name + "'}";
    }
}

What is a Functional Interface?

A functional interface (SAM) contains exactly one abstract method, optionally with default or static methods; it can be annotated with @FunctionalInterface.

@FunctionalInterface
public interface Runnable {
    void run();
}

Only a functional interface variable can be assigned a lambda expression.

What is the purpose of Functional Interfaces?

They allow lambda expressions to be passed where an interface implementation is required, enabling concise code.

Each lambda expression implicitly provides an implementation for a functional interface.

Custom Functional Interface Example

package com.isea.java;
@FunctionalInterface
public interface IMyInterface {
    void study();
}
public class TestIMyInterface {
    public static void main(String[] args) {
        IMyInterface iMyInterface = () -> System.out.println("I like study");
        iMyInterface.study();
    }
}

Four Core Functional Interfaces

1. Consumer – void accept(T t) (parameter, no return) 2. Supplier – T get() (no parameter, returns value) 3. Predicate – boolean test(T t) (parameter, returns boolean) 4. Function – R apply(T t) (parameter, returns value)

Method References

When a lambda matches a method signature, a method reference can further simplify the code.

Constructor reference:

package com.isea.java;
import java.util.function.Supplier;
public class TestLambda {
    public static void main(String[] args) {
        Supplier<Student> s = Student::new;
    }
}

Class::instanceMethod:

package com.isea.java;
import java.util.TreeSet;
public class TestLambda {
    public static void main(String[] args) {
        TreeSet<String> set = new TreeSet<>(String::compareTo);
        set.add("Hello");
        set.add("isea_you");
        set.forEach(System.out::println);
    }
}

Class::staticMethod:

package com.isea.java;
import java.util.stream.Stream;
public class TestLambda {
    public static void main(String[] args) {
        Stream<Double> stream = Stream.generate(Math::random);
        stream.forEach(System.out::println);
    }
}

The author reflects on the effort of writing this tutorial late at night, emphasizing steady progress and deep understanding through practice.

JavaStreamsLambda ExpressionsFunctional InterfacesMethod References
Architect's Must-Have
Written by

Architect's Must-Have

Professional architects sharing high‑quality architecture insights. Covers high‑availability, high‑performance, high‑stability designs, big data, machine learning, Java, system, distributed and AI architectures, plus internet‑driven architectural adjustments and large‑scale practice. Open to idea‑driven, sharing architects for exchange and learning.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.