Version: Next
方法引用
- 当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用
- 方法引用可以看做是Lambda表达式深层次的表达。
- 方法引用就是Lambda表达式,也就是函数式接口的一个实例,通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖
要求:
- 实现接口的抽象方法的参数列表返回值类型,必须与方法引用的方法的参数列表和返回值类型一致
格式
::
类::方法名
对象::方法名
三种使用情况:
对象::实例方法名
类::静态方法名
类::实例方法名
对象::实例方法
- Consumer中的void accept(T t)
- PrintStream中的void println(T t)
Lambda表达式
这个例子中,lambda体中使用的是
System.out.println()
,它是一个已经实现的方法,就可以使用方法引用
public static List<User> getUsers() {
User user1 = new User(1, "a", 20);
User user2 = new User(2, "b", 21);
User user3 = new User(3, "c", 22);
User user4 = new User(4, "d", 23);
User user5 = new User(5, "e", 24);
return Arrays.asList(user1, user2, user3, user4, user5);
}
@Test
public void testMethodReference1() {
List<User> users = getUsers();
Consumer<User> consumer = user -> {
System.out.println(user);
};
consumer.accept(users.get(0));
}
- 方法引用
@Test
public void testMethodReference1_1() {
List<User> users = getUsers();
PrintStream printStream = System.out;
Consumer<User> consumer = printStream::println;
consumer.accept(users.get(0));
}
- Supplier中的T get()
- User中的String getName()
- Lambda表达式
@Test
public void testMethodReference1_2() {
List<User> users = getUsers();
Supplier<String> supplier = () -> users.get(0).getName();
System.out.println(supplier.get());
}
- 方法引用
@Test
public void testMethodReference1_3() {
List<User> users = getUsers();
Supplier<String> supplier = users.get(0)::getName;
System.out.println(supplier.get());
}
类::静态方法名
- Comparator中的int compare(T t1, T t2)
- Integer中的int compare(T t1, T t2)
@Test
public void testMethodReference2() {
List<User> users = getUsers();
User user1 = users.get(0);
User user2 = users.get(1);
int age1 = user1.getAge();
int age2 = user2.getAge();
Comparator<Integer> comparator = (t1, t2) -> Integer.compare(t1, t2);
System.out.println(comparator.compare(age1, age2));
}
@Test
public void testMethodReference2_1() {
List<User> users = getUsers();
User user1 = users.get(0);
User user2 = users.get(1);
int age1 = user1.getAge();
int age2 = user2.getAge();
Comparator<Integer> comparator = Integer::compare;
System.out.println(comparator.compare(age1, age2));
}
- Function中的R apply(T t)
- Math中的Long round(Double d)
@Test
public void testMethodReference2_2() {
Function<Double, Long> function = d -> Math.round(d);
System.out.println(function.apply(22.3));
}
@Test
public void testMethodReference2_2() {
Function<Double, Long> function = Math::round;
System.out.println(function.apply(22.3));
}
类::实例方法
- Comparator中的int compare(T t1, T t2)
- String中的int t1.compareTo(t2)
- 虽然参数列表不匹配,但是其中一个参数是方法调用者
@Test
public void testMethodReference3() {
Comparator<String> comparator = (s1, s2) -> s1.compareTo(s2);
System.out.println(comparator.compare("a", "c"));
}
@Test
public void testMethodReference3() {
Comparator<String> comparator = String::compareTo;
System.out.println(comparator.compare("a", "c"));
}
- BiPredicate中的boolean test(T t1, T t2)
- String中的boolean t1.equals(t2)
@Test
public void testMethodReference3_1() {
BiPredicate<String, String> biPredicate = (s1, s2) -> s1.equals(s2);
System.out.println(biPredicate.test("a", "a"));
}
@Test
public void testMethodReference3_1() {
BiPredicate<String, String> biPredicate = String::equals;
System.out.println(biPredicate.test("a", "a"));
}
- Function中的 R apply(T t)
- User中的String getName()
- t就作为getName()的调用者
@Test
public void testMethodReference3_2() {
Function<User, String> function = user -> user.getName();
System.out.println(function.apply(new User(1, "A", 20)));
}
@Test
public void testMethodReference3_2() {
Function<User, String> function = User::getName;
System.out.println(function.apply(new User(1, "A", 20)));
}
例:遍历集合
- 增强for循环
- 使用foreach(Consumer),里面写lambda表达式
- 使用foreach(Consumer),当Consumer参数列表和Lambda体参数列表一致时,可以使用方法引用
- 增强for循环
@Test
public void testForeach1() {
List<User> users = getUsers();
for (User user : users) {
System.out.println(user);
}
}
User{id=1, name='a', age=20}
User{id=2, name='b', age=21}
User{id=3, name='c', age=22}
User{id=4, name='d', age=23}
User{id=5, name='e', age=24}
- foreach(Consumer) lambda表达式
@Test
public void testForeach1() {
List<User> users = getUsers();
users.forEach(user -> System.out.println(user.getName()));
}
a
b
c
d
e
- foreach(Consumer) 方法引用
@Test
public void testForeach1() {
List<User> users = getUsers();
users.forEach(user -> System.out.println(user));
}
因为Consumer的参数为user, lambda体中的方法参数也为user,就可以用方法引用,改写为:
@Test
public void testForeach1() {
List<User> users = getUsers();
users.forEach(System.out::println);
}
User{id=1, name='a', age=20}
User{id=2, name='b', age=21}
User{id=3, name='c', age=22}
User{id=4, name='d', age=23}
User{id=5, name='e', age=24}