Functional Programming & Streams
Method References
A method reference names an existing method where a lambda is expected:
String::length, System.out::println, User::new. When it's clearer than the lambda, use it; when it isn't, don't.- Five kinds: static, bound instance, unbound instance, constructor, array constructor
ClassName::instanceMethod— the first lambda argument becomes the receiverexpr::instanceMethodcaptures the receiver now, calls later- Prefer method references when shorter and clearer (EJ 43)
| Kind | Syntax | Equivalent lambda |
|---|---|---|
| Static | Integer::parseInt | s -> Integer.parseInt(s) |
| Bound (receiver fixed) | System.out::println | x -> System.out.println(x) |
| Unbound (receiver = 1st arg) | String::toLowerCase | s -> s.toLowerCase() |
| Constructor | ArrayList::new | () -> new ArrayList<>() |
| Array constructor | String[]::new | n -> new String[n] |
The unbound form is the one worth internalizing: in Comparator.comparing(Person::getName), each Person flowing through becomes the receiver of getName. With two parameters, String::compareToIgnoreCase means (a, b) -> a.compareToIgnoreCase(b).
people.stream()
.map(Person::getName) // unbound
.filter(Objects::nonNull) // static
.sorted(String::compareToIgnoreCase) // unbound, 2-arg
.forEach(System.out::println); // bound
List<Set<String>> groups = names.stream()
.collect(groupingBy(String::length, mapping(s -> s, toCollection(TreeSet::new))));