请教一个 lambda 表达式的问题

2021-07-05 19:35:00 +08:00
 chonh

比如我要将 List<String>转为 Set<Long>可以这么写:

1763 次点击
所在节点    Java
2 条回复
codergrowing
2021-07-05 20:45:45 +08:00
去查了一圈资料,大概是弄懂了原因,我尝试说明一下:

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
chonh
2021-07-05 22:20:41 +08:00
@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.

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/787715

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX