比如我要将 List<String>转为 Set<Long>可以这么写:
1
codergrowing 2021-07-05 20:45:45 +08:00 2
去查了一圈资料,大概是弄懂了原因,我尝试说明一下:
strs.stream().map(Long::valueOf).collect(LinkedHashSet::new, HashSet::add, HashSet::addAll); 不使用 Method Reference 的形式可以写成: strs.stream().collect(LinkedHashSet::new, (set, element) -> set.add(element), (set1, set2) -> set1.addAll(set2)); 这样看,(set, element) -> set.add(element) 是不是符合 BiConsumer 的 void accept(T t, U u); 方法定义了呢? 而为什么(set, element) -> set.add(element) 可以写成 HashSet::add 的形式: 不管是 add 还是 addAll 都是实例方法,当实例方法被用做 Method Reference 的时候,receiver 会将 this 作为第一个参数传入,比如 Oracle 官方 Tutorial ( https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html )中的这个例子: String[] stringArray = { "Barbara", "James", "Mary", "John", "Patricia", "Robert", "Michael", "Linda" }; Arrays.sort(stringArray, String::compareToIgnoreCase); String::compareToIgnoreCase 等价于 (a, b) -> a.compareToIgnoreCase(b); 只不过是写成 String::compareToIgnoreCase 这种形式时,编译器会自动帮你处理改写。 参考: https://moandjiezana.com/blog/2014/understanding-method-references/ http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html |
2
chonh OP @codergrowing 感谢回答!
你给的这个链接讲解得很清楚: https://moandjiezana.com/blog/2014/understanding-method-references/ “当实例方法被用做 Method Reference 的时候,receiver 会将 this 作为第一个参数传入” 这句话没看太懂。我感觉是:实例方法转为 lambda 时,lambda 的第一个参数作为实例对象,lambda 的后续参数作为实例方法的参数。 原文的说法是: when converting a method reference to a lambda, “if the desugared method is an instance method, the receiver is considered to be the first argument”. Also, the lambda’s remaining arguments are passed as arguments to the referred method. |