FP = Code as Data
Using function (or a piece of code) like a variable that can be passed around as method arguments and returns.
In FP, functions are first-class citizens!
How Java achieves FP:
Lambda Expression = A shortcut for writing small anonymous functions.
Lambdas can be used where functional interfaces are expected.
Functional Interface = An interface with only one abstract function, like like Runnable, Callable, or Comparator.
Method Reference = Lambda shorthand calling existing method. Example: System.out::println
Runnable task = new Runnable() {
@Override
public void run() {
System.out.println("Running with Anonymous Class");
}
};
task.run();
Runnable task = () -> System.out.println("Running with Lambda Expression");
task.run();
Note: Runnable is a functional interface because it defines only one method run()
parameter -> expression
or
(parameters) -> { statements; }
Examples:
// no parameter
() -> System.out.println("Simple lambda!")
// 1 parameter, inferred type
n -> n * n
// Multiple parameters, with types
(int x, int y) -> x + y
// With a block of statements
(x, y) -> {
int sum = x + y;
System.out.println(sum);
return sum;
}
Interface | Method | Example
------------------| ----------------- | ------------------
Predicate<T> | boolean test(T t) | x -> x > 0
Function<T, R> | R apply(T t) | s -> s.length()
Consumer<T> | void accept(T t) | System.out::println
Supplier<T> | T get() | () -> Math.random()
BinaryOperator<T> | T apply(T, T) | (a, b) -> a + b
List<String> names = List.of("Alice", "Bob", "Charlie");
names.stream()
.filter(n -> n.startsWith("C"))
.map(String::toUpperCase)
.forEach(System.out::println);
Lambda | Method Reference
------------------------------ | -------------------
x -> System.out.println(x) | System.out::println
(x, y) -> x.compareTo(y) | String::compareTo
(a, b) -> Math.max(a, b) | Math::max
() -> new ArrayList<>() | ArrayList::new
s -> s.toUpperCase() | String::toUpperCase
obj -> obj.someMethod() | SomeClass::someMethod
(x, y) -> Objects.equals(x, y) | Objects::equals
import java.util.*;
public class LambdaVsMethodReference {
public static void main(String[] args) {
List<Integer> numbers = List.of(5, 10, 3, 8, 12);
// Using Lambda
Optional<Integer> max1 = numbers.stream()
.reduce((a, b) -> Math.max(a, b));
// Using Method Reference
Optional<Integer> max2 = numbers.stream()
.reduce(Math::max);
System.out.println("Max with lambda: " + max1.orElse(null));
System.out.println("Max with method reference: " + max2.orElse(null));
}
}
Note: Stream.reduce takes a BinaryOperator<T>, which is a functional interface:
The term "Lambda" is associated with λ-calculus (lambda calculus) in math.