V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
chonh
V2EX  ›  Java

请教一个 lambda 表达式的问题

  •  
  •   chonh · 2021-07-05 19:35:00 +08:00 · 1987 次点击
    这是一个创建于 1270 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    • strs.stream().map(Long::valueOf).collect(LinkedHashSet::new, HashSet::add, HashSet::addAll);
    • collect 的三个参数分别为:Supplier,BiConsumer,BiConsumer;
    • 但 HashSet::add 和 HashSet::addAll 看着都是 Function;
    • 他们是怎么和 BiConsumer 匹配的?
    2 条回复    2021-07-05 22:20:41 +08:00
    codergrowing
        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
    chonh
        2
    chonh  
    OP
       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.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2777 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 15:17 · PVG 23:17 · LAX 07:17 · JFK 10:17
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.