【问题标题】:Question about ordering of parameters of Collector and Function in Java Streams关于Java Streams中Collector和Function的参数排序问题
【发布时间】:2022-01-25 18:01:10
【问题描述】:

所以我正在研究 Java Streams,我对某些参数的顺序的含义有一些疑问。

一些上下文:

public static List<Person> createPeople() {
    return List.of(new Person("Sara", 20), 
                   new Person("Sara", 22), 
                   new Person("Bob", 20), 
                   new Person("Paula",32), 
                   new Person("Paul", 32), 
                   new Person("Jack", 3), 
                   new Person("Jack", 72), 
                   new Person("Jill", 11));
    }
    

List<Person> people = Section.createPeople();

考虑以下代码:

Map<String, Integer> countByName3 = people.stream()
                                          .collect(groupingBy(Person::getName,
                                                              collectingAndThen(counting(), Long::intValue)));

这段代码的重点是输出一个键值对,其中键是人名,值是具有该特定名称的人数。

现在我的理解是,collect 方法将由 Collectors 类中的函数(例如 groupingBy)生成的 Collector 对象作为其参数。

我也明白其中一些方法的参数中有一个函数。让我感兴趣的是函数和收集器的顺序在生成收集器对象的方法中所起的作用。

例如,groupingBy() 按顺序(函数、收集器)获取参数,而 collectAndThen() 按顺序(收集器、函数)获取参数。如果我没记错的话,两者都会返回 Collectors。

因此,颠倒顺序的含义是什么,它是否表明某些事物是如何在幕后处理的?如果命令背后有不同/含义,我可以得到解释吗?

非常感谢。

【问题讨论】:

    标签: java java-stream


    【解决方案1】:

    这里没有什么神奇的事情发生。 Collectors 只是一个类。像任何其他人一样。它有静态方法。你可以调用它们,这里绝对没有魔法。如果需要,您可以使用返回 Collector 类型实例的静态方法创建自己的类。

    鉴于它们只是方法,语言中绝对没有关于参数顺序的固有内容。 collectingAndThen方法的作者分别对groupingBy方法做出了决定。就是这样。

    如果您想解释为什么这些作者决定将论点放在这些顺序中,您必须问他们 - 这对于 Stack Overflow 来说不是一个合适的问题,所以我会给您带来疑问并假设你知道这一点,并要求人们就原因发表意见。这也不太适合 SO。但是,为了满足你:

    这对我来说很有意义。 collectingAndThen 的顺序与该方法的名称相同:“创建一个新的收集器,首先应用此收集器(第一个参数),但在收集后应用此完成转换(第二个参数)”。

    参数按照解释其作用的顺序排列。

    groupingBy,做同样的事情:通过按某个键分组创建一个收集器;要导出此密钥,请通过此转换功能在流中折腾所有东西。然后,通过使用 THIS 收集器应用这个键值来实际收集它。

    两者都在这个“按照你提到参数的顺序,如果你能解释它的作用”顺序。事实上groupingBy 的第一个“东西”恰好是Function,而它的第二个“东西”恰好是Collector,而对于collectingAndThen,它的第一个“东西”是Collector 和它的第二个“事情”是Function 完全是巧合。

    【讨论】:

    • 感谢您的回答。所以要明确一点,在 groupingBy 函数中,是先应用函数,然后创建收集器,而使用 collectAndThen 函数,我们先创建收集器,然后将函数应用于收集器?论据的顺序表明这是如何发生的?
    • 'first' 和 'second' 对于流来说很棘手,它们可以是并行的。对于流中的任何单个项目,groupingBy 将首先通过函数折腾每个项目,然后创建 X 个子流,根据派生密钥将所有项目分组到这些子流中的一个。然后使用收集器(第二个参数)将这些子流转换为对象。
    • 使用collectingAndThen,没有子流-使用提供的收集器将项目流收集到单个对象中。然后该对象被转换。该功能不适用于收集器,那会有点愚蠢(只是......自己做)。它应用于收集器制作的对象。收集器用于将项目流减少为单个答案。
    • 感谢您的详尽回答。我想我现在有了更好的理解。
    猜你喜欢
    • 2010-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-16
    • 1970-01-01
    • 2016-12-02
    • 2019-04-10
    • 1970-01-01
    相关资源
    最近更新 更多