Java 8 Lambda Expressions and Method References

Benefits of New Features

  • Improved Performance
  • Reduced Code Verbosity (Lambda Expressions)
  • Powerful Stream API
  • Enhanced Parallel Processing Support
  • Minimized NullPointerException Risks: Optional
  • Nashorn Engine for Running JS Applications on JVM

Lambda Expressions

A Lambda Expression is an anonymous function, representing a block of code that can be passed around as data.

Core Concept

It acts as a concrete implementation of a functional interface.

Usage Syntax

(parameter list) -> expression or code block
  • ->: Lambda operator
  • Left side: Parameter list matching the abstract method of the functional interface.
  • Right side: Implementation body for the abstract method.

Key Points:

  • Parameter types can be omitted (type inference). Parentheses can be omitted for a single parameter.
  • The body can be a single expression or a block in {}. Braces and the return keyword can be omitted for a single expression that returns a value.

Syntax 1: No Parameters, No Return Value

Runnable task1 = new Runnable() {
    @Override
    public void run() {
        System.out.println("Running task1");
    }
};
task1.run();

// Using Lambda
Runnable task2 = () -> System.out.println("Running task2");
task2.run();

Syntax 2: One Parameter, No Return Value

Consumer<String> printer1 = new Consumer<>() {
    @Override
    public void accept(String msg) {
        System.out.println(msg);
    }
};
printer1.accept("Message1");

// Using Lambda
Consumer<String> printer2 = (String s) -> System.out.println(s);
printer2.accept("Message2");

// With type inference
Consumer<String> printer3 = (s) -> System.out.println(s);
printer3.accept("Message3");

// Omitting parentheses for single parameter
Consumer<String> printer4 = s -> System.out.println(s);
printer4.accept("Message4");

Syntax 3: Multiple Parameters, Return Value

Comparator<Integer> comp1 = new Comparator<>() {
    @Override
    public int compare(Integer a, Integer b) {
        System.out.println(a);
        System.out.println(b);
        return a - b;
    }
};

// Using Lambda
Comparator<Integer> comp2 = (Integer a, Integer b) -> {
    System.out.println(a);
    System.out.println(b);
    return a - b;
};

// With type inference
Comparator<Integer> comp3 = (a, b) -> {
    System.out.println(a);
    System.out.println(b);
    return a - b;
};

// Single expression body (return implied)
Comparator<Integer> comp4 = (a, b) -> a - b;

Functional Interfaces

  • An interface with exactly one abstract method is a functional interface.
  • Lambda expressions can create instances of such interfaces. If the lambda throws a checked exception, it must be declared in the interface's abstract method signature.
  • The @FunctionalInterface annotation can be used for verification.
  • The java.util.function package contains many built-in functional interfaces.

Core Built-in Functional Interfaces

Example Usage

// Consumer example
public void processValue(double value, Consumer<Double> handler) {
    handler.accept(value);
}
// Test call
processValue(10.5, val -> System.out.println(val));

// Predicate example
public List<String> filterList(List<String> input, Predicate<String> condition) {
    List<String> result = new ArrayList<>();
    for (String item : input) {
        if (condition.test(item)) {
            result.add(item);
        }
    }
    return result;
}
// Test call: filter strings containing "java"
List<String> filtered = filterList(list, str -> str.contains("java"));

Method References

Method references provide a shorthand syntax for lambda expressions when the implementation simply calls an existing method.

Core Requirement

The parameter list and return type of the functional interface's abstract method must match the referenced method.

Use Case

Use when the lambda body directly calls an existing method.

Case 1: Instance Method Reference via Object

// Lambda
Consumer<String> c1 = str -> System.out.println(str);
c1.accept("Hello");

// Method Reference (System.out is an instance of PrintStream)
Consumer<String> c2 = System.out::println;
c2.accept("World");

// Another example with a custom object
Employee emp = new Employee("Alice");
Supplier<String> nameSupplier1 = () -> emp.getName();
System.out.println(nameSupplier1.get());

Supplier<String> nameSupplier2 = emp::getName;
System.out.println(nameSupplier2.get());

Case 2: Static Method Reference via Class

// Lambda
Comparator<Integer> comp1 = (x, y) -> Integer.compare(x, y);

// Method Reference
Comparator<Integer> comp2 = Integer::compare;

// Another example
Function<Double, Long> rounder1 = num -> Math.round(num);
Function<Double, Long> rounder2 = Math::round;

Case 3: Instance Method Reference via Class (First Parameter as Target)

// Lambda for comparing strings
Comparator<String> strComp1 = (s1, s2) -> s1.compareTo(s2);

// Method Reference (compareTo is an instance method of String)
Comparator<String> strComp2 = String::compareTo;

// Lambda for checking equality
BiPredicate<String, String> equalityCheck1 = (str1, str2) -> str1.equals(str2);
BiPredicate<String, String> equalityCheck2 = String::equals;

Constructor References

Similar to method references, but used to refer to constructors.

Format

ClassName::new

Case 1: No-arguement Constructor

// Lambda
Supplier<Employee> empSupplier1 = () -> new Employee();
// Constructor Reference
Supplier<Employee> empSupplier2 = Employee::new;

Case 2: Constructor with Arguments

// Lambda for one-argument constructor
Function<Integer, Employee> empCreator1 = id -> new Employee(id);
// Constructor Reference
Function<Integer, Employee> empCreator2 = Employee::new;

// Lambda for two-argument constructor
BiFunction<Integer, String, Employee> empCreator3 = (id, name) -> new Employee(id, name);
// Constructor Reference
BiFunction<Integer, String, Employee> empCreator4 = Employee::new;

Array References

Treat an array type as a special class for reference.

Format

Type[]::new

Example

// Lambda to create a String array
Function<Integer, String[]> arrayCreator1 = size -> new String[size];
// Array Reference
Function<Integer, String[]> arrayCreator2 = String[]::new;

Tags: Java 8 Lambda Expressions Functional Interface Method Reference Constructor Reference

Posted on Thu, 14 May 2026 17:39:39 +0000 by illzz