Lambdas in Java are anonymous functions that allow you to write more concise and functional-style code. They were introduced in Java 8 as a way to implement functional interfaces more elegantly.

A lambda expression is essentially a short block of code that takes parameters and returns a value. It’s similar to methods, but doesn’t need a name and can be implemented as an assignment to a Functional Interface type.

Syntax

Lambda Syntax Structure The basic syntax of a lambda expression follows this pattern:

(parameters) -> expression
// or
(parameters) -> { statements; }

Components:

  • Parameters: Input parameters (can be empty)
  • Arrow operator (->): Separates parameters from body
  • Body: Either a single expression or a block of statements

Declaration

// Using built-in functional interfaces
Runnable task = () -> System.out.println("Running task");
 
Predicate<String> isEmpty = s -> s.isEmpty();
 
Function<String, Integer> stringLength = s -> s.length();
 
Comparator<String> lengthComparator = (s1, s2) -> 
    Integer.compare(s1.length(), s2.length());
 
// Custom functional interface
@FunctionalInterface
interface Calculator {
    int calculate(int a, int b);
}
 
Calculator add = (a, b) -> a + b;
Calculator multiply = (a, b) -> a * b;

Variable Capture

Lambdas can only capture variables that are final or effectively final(variables that are not reassigned after initialisation).

public void demonstrateCapture() {
    int multiplier = 10;        // effectively final
    String prefix = "Result: "; // effectively final
    
    Function<Integer, String> formatter = x -> 
        prefix + (x * multiplier);
    
    // This would cause a compilation error:
    // multiplier = 20; // Cannot modify captured variable
}

Currying

Function<Integer, Function<Integer, Integer>> represents currying.
Transforming a function that takes multiple arguments into a sequence of functions that each take a single argument.

// Traditional two-parameter function implemented with currying
// The first Function returns a second Function that adds the first Function's agument to the second function's argument
Function<Integer, Function<Integer, Integer>> add = 
    x -> y -> x + y;
 
// Usage
Function<Integer, Integer> add5 = add.apply(5);
Integer result = add5.apply(3); // result = 8
 
// Or in one line
Integer directResult = add.apply(5).apply(3); // result = 8

Key Benefits of Lambdas

  • Conciseness: Less boilerplate code compared to anonymous classes
  • Readability: More expressive and functional programming style
  • Type inference: Compiler can often infer parameter types
  • Closure support: Can capture variables from enclosing scope