Method References in Depth
The four shapes of a method reference, what each one expands to, and when a lambda is clearer.
Open this lesson in the learning hubKey points
- Static:
Main::tagbecomess -> Main.tag(s). The stream element is the argument. - Unbound instance:
String::lengthbecomess -> s.length(). The element is the receiver. - Bound instance:
prefix::concatbecomess -> prefix.concat(s). The receiver is captured once, right there. - Constructor:
User::newbecomess -> new User(s), andString[]::newbecomes an array factory. - A method reference is shorter, never faster. Use a lambda the moment arguments need reordering or extra work.
- Watch the bound form: it captures the receiver when the reference is created, not when the stream runs.
Example
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
public class Main {
record User(String name) {
String shout() {
return name.toUpperCase();
}
}
static String tag(String s) {
return "#" + s;
}
public static void main(String[] args) {
List<String> names = List.of("ada", "grace");
// 1. Static: Main::tag is s -> Main.tag(s)
System.out.println("static : " + names.stream().map(Main::tag).toList());
// 2. Unbound: String::length is s -> s.length()
System.out.println("unbound : " + names.stream().map(String::length).toList());
// 3. Bound: prefix::concat is s -> prefix.concat(s)
String prefix = ">> ";
System.out.println("bound : " + names.stream().map(prefix::concat).toList());
// 4. Constructor: User::new is s -> new User(s)
List<User> users = names.stream().map(User::new).toList();
System.out.println("ctor : " + users.stream().map(User::shout).toList());
// The receiver of a bound reference is captured once, when the reference is created.
BinaryOperator<Integer> ref = Integer::sum;
System.out.println("sum ref : " + ref.apply(2, 3));
// Reach for a lambda when the arguments need reordering or extra work.
System.out.println("no ref : " + names.stream().map(n -> n.substring(0, 1) + ".").toList());
System.out.println("sorted : " + Stream.of("pear", "fig")
.sorted(Comparator.comparing(String::length)).toList());
}
}
Four shapes, one rule: work out what the element becomes, the receiver or the argument.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Streams course, and every lesson in it is listed on the Streams contents page.