Method References
When a lambda only calls an existing method
A lambda often contains no new logic and simply passes its argument to an existing method. In that case, the code can be shortened with a method reference.
Function<String, Integer> length1 = text -> text.length();
Function<String, Integer> length2 = String::length;
Both variables describe the same behavior.
The String::length form does not call the method when it is declared —
it passes behavior that will be invoked later through the functional interface.
Main method-reference forms
In practice, four forms appear most often:
Function<String, Integer> parse = Integer::parseInt;
Consumer<String> print = System.out::println;
Function<String, String> trim = String::trim;
Supplier<ArrayList<String>> create = ArrayList::new;
Integer::parseInt— a reference to a static method;System.out::println— a method of a specific object;String::trim— an instance method where the object itself is supplied as an argument of the functional interface;ArrayList::new— a constructor reference.
The number and types of parameters must match the expected functional interface.
For example, String::trim fits Function<String, String>:
the input string becomes the object on which trim() is called,
and the method result becomes the function result.
Choose the readable form
A method reference is useful when it actually makes the intention clearer. If a lambda contains an additional check, several calls, or a calculation, a regular lambda is usually easier to read.
Predicate<String> isNotBlank = text -> !text.isBlank();
Here, trying to replace the lambda with a method reference at any cost would only make the code more complicated. Method references are not a separate computation mechanism; they are a more compact form for already existing compatible behavior.