Java 8 Pocket Guide (2014)
Part II. Platform
Chapter 19. Lambda Expressions
Lamda expressions (λEs), also known as closures, provide a means to represent anonymous methods. Supported by Project Lambda, λEs allow for the creation and use of single method classes. These methods have a basic syntax that provides for the omission of modifiers, the return type, and optional parameters. The specification for λEs is set out in JSR 335, which is divided into seven parts: functional interfaces, lambda expressions, method and constructor references, poly expressions, typing and evaluation, type inference, and default methods. This chapter focuses on the first two.
λEs Basics
λEs must have a functional interface (FI). An FI is an interface that has one abstract method and zero or more default methods. FIs provide target types for lambda expressions and method references, and ideally should be annotated with @FunctionalInterface to aid the developer and compiler with design intent.
@FunctionalInterface
public interface Comparator<T> {
// Only one abstract method allowed
int compare(T o1, T o2);
// Overriding allowed
boolean equals(Object obj);
// Optional default methods allowed
}
λEs Syntax and Example
Lambda expressions typically include a parameter list, a return type, and a body.
(parameter list) -> { statements; }
Examples of λEs include:
() -> 66
(x,y) -> x + y
(Integer x, Integer y) -> x*y
(String s) -> { System.out.println(s); }
This simple JavaFX GUI application adds text to the title bar when the button is pressed. The code makes use of the EventHandler functional interface with the one abstract method, handle().
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class JavaFxApp extends Application {
@Override
public void start(Stage stage) {
Button b = new Button();
b.setText("Press Button");
// Anonymous inner class usage
b.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
stage.setTitle("λEs rock!");
}
});
StackPane root = new StackPane();
root.getChildren().add(b);
Scene scene = new Scene(root, 200, 50);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
To refactor this anonymous inner class into a lambda expression, the parameter type needs to be either (ActionEvent event) or just (event) and the desired functionality needs to be provided as statements in the body.
// Lambda Expression usage
b.setOnAction((ActionEvent event) -> {
stage.setTitle("λEs rock!");
});
TIP
Modern IDEs have features to convert anonymous inner classes to lambda expressions.
See Comparator Functional Interface for another example of lambda expressions with the Comparator functional interface.
Method and Constructor References
A method reference refers to an existing method without invoking it. Types include static method reference, instance method of particular object, super method of particular object, and instance method of arbitrary object of particular type. Method references also include class constructor reference and array constructor reference.
"some text"::length // Get length of String
String::length // Get length of String
CheckAcct::compareByBalance // Static method ref
myComparator::compareByName // Inst method part obj
super::toString // Super method part object
String::compareToIgnoreCase // Inst method arb obj
ArrayList<String>::new // New ArrayList constructor
Arrays::sort // Sort array elements
Specific Purpose Functional Interfaces
Annotated FIs listed in Table 19-1 have been established for specific purposes relative to the packages/APIs in which they reside. Not all functional interfaces in the Java SE API are annotated.
Table 19-1. Specific-purpose FIs
API |
Class |
Method |
AWT |
KeyEventDispacter |
dispatchKeyEvent (KeyEvent e) |
AWT |
KeyEventPostProcessor |
postProcessKeyEvent (KeyEvent e) |
IO |
FileFilter |
accept(File pathname) |
IO |
FilenameFilter |
accept(File dir, String name) |
LANG |
Runnable |
run () |
NIO |
DirectorStream |
iterator () |
NIO |
PathMatcher |
matches (Path path) |
TIME |
TemporalAdjuster |
adjustInto (Temporal temporal) |
TIME |
TemporalQuery |
queryFrom (TemporalAccessor temporal) |
UTIL |
Comparator |
compare (T o1, T o2) |
CONC |
Callable |
call () |
LOG |
Filter |
isLoggable (LogRecord record) |
PREF |
PreferenceChangeListener |
preferenceChange (PreferenceChangeEvent evt) |
General Purpose Functional Interfaces
The java.util.function package is made up of general purpose FIs for the primary use of features of the JDK. Table 19-2 lists them all.
Table 19-2. Functional interfaces functional package
Consumer |
accept (T t) |
BiConsumer |
accept (T t, U u) |
ObjDoubleConsumer |
accept (T t, double value) |
ObjIntConsumer |
accept (T t, int value) |
ObjLongConsumer |
accept (T t, long value) |
DoubleConsumer |
accept (double value) |
IntConsumer |
accept (int value) |
LongConsumer |
accept (long value) |
Function |
apply (T t) |
BiFunction |
apply (T t, U u) |
DoubleFunction |
apply (double value) |
IntFunction |
apply (int value) |
LongFunction |
apply (long value) |
BinaryOperator |
apply (Object, Object) |
ToDoubleBiFunction |
applyAsDouble (T t, U u) |
ToDoubleFunction |
applyAsDouble (T value) |
IntToDoubleFunction |
applyAsDouble (int value) |
LongToDoubleFunction |
applyAsDouble(long value) |
DoubleBinaryOperator |
applyAsDouble (double left, double right) |
ToIntBiFunction |
applyAsInt (T t, U u) |
ToIntFunction |
applyAsInt (T value) |
LongToIntFunction |
applyAsInt (long value) |
DoubleToIntFunction |
applyAsInt(double value) |
IntBinaryOperator |
applyAsInt (int left, int right) |
ToLongBiFunction |
applyAsLong (T t, U u) |
ToLongFunction |
applyAsLong (T value) |
DoubleToLongFunction |
applyAsLong (double value) |
IntToLongFunction |
applyAsLong (int value) |
LongBinaryOperator |
applyAsLong (long left, long right) |
BiPredicate |
test (T t, U u) |
Predicate |
test (T t) |
DoublePredicate |
test (double value) |
IntPredicate |
test (int value) |
LongPredicate |
test (long value) |
Supplier |
get() |
BooleanSupplier |
getAsBoolean() |
DoubleSupplier |
getAsDouble() |
IntSupplier |
getAsInt() |
LongSupplier |
getAsLong() |
UnaryOperator |
identity() |
DoubleUnaryOperator |
identity() |
IntUnaryOperator |
applyAsInt (int operand) |
LongUnaryOperator |
applyAsInt (long value) |
Resources for λEs
This section provides links to tutorials and community resources about λEs.
Tutorials
Comprehensive tutorials are provided by Oracle and Maurice Naftalin.
§ The Java Tutorials: Lambda Expressions
§ Maurice Naftalin’s Lambda FAQ: “Your questions answered: all about Lambdas and friends”
Community Resources
Online bulletin boards, mailing lists, and instructional videos provide support for learning and using λEs:
§ λEs Forum Board at CodeRanch: Online bulletin board
§ λEs Mailing List: Technical discussions related to Project Lambda
§ Oracle Learning Library on YouTube