【问题标题】:What's the difference between groupingby and mapping in Collectors (Java)?Collectors (Java) 中的 groupingby 和 mapping 有什么区别?
【发布时间】:2017-04-11 02:53:26
【问题描述】:

看看这段代码。

// group by price, uses 'mapping' to convert List<Item> to Set<String>
    Map<BigDecimal, Set<String>> result =
            items.stream().collect(
                    Collectors.groupingBy(Item::getPrice,
                            Collectors.mapping(Item::getName, Collectors.toSet())
                    )
            );

groupingBy 和 Mapping 可以互换吗?它们有什么区别?

对于 collect() 中的第三个参数,如果我使用 Collectors.toList() 而不是 Collectors.toSet(),我会得到相同的输出类型 Map 吗?我听说 toList() 是一个更受欢迎的选项。

【问题讨论】:

  • toList() “更受欢迎”,因为它是未指定其他收集器时的默认值,即 Collectors.groupingBy(Item::getPrice)Collectors.groupingBy(Item::getPrice, Collectors.toList()) 具有相同的结果。

标签: java java-8 java-stream collectors


【解决方案1】:

不,两者完全不同。

Collectors.groupingBy 接受一个函数,该函数创建键并返回一个收集器,该收集器返回一个从键到流中具有相同键的对象集合的映射。

Collectors.mapping,另一方面,接受一个函数和另一个收集器,并创建一个新的收集器,它首先应用该函数,然后使用给定的收集器收集映射的元素。因此,以下是等价的:

items.stream().map(f).collect(c);
items.stream().collect(Collectors.mapping(f, c));

Collectors.mapping 在没有流但需要直接传递收集器的情况下最有用。这种情况的一个例子是使用Collectors.groupingBy

items.stream().collect(Collectors.groupingBy(Item::getPrice, Collectors.toSet()))

产生Map&lt;BigDecimal,Set&lt;Item&gt;&gt;(假设getPrice() 返回BigDecimal)。然而,

items.stream().collect(Collectors.groupingBy(Item::getPrice,
    Collectors.mapping(Item::getName, Collectors.toSet())))

返回Map&lt;BigDecimal,Set&lt;String&gt;&gt;。在收集物品之前,它首先对它们应用Item.getName

【讨论】:

    【解决方案2】:

    groupingBy 和 Mapping 可以互换吗?

    不,它们完全不同。 groupingBy 允许您创建一个Map,其中键是传递给groupingBy 的第一个参数,值是Stream 元素类型的List

    Collectors.groupingBy(Item::getPrice) 会生成一个Map&lt;BigDecimal, List&lt;Item&gt;&gt;(假设Item::getPrice 返回一个BigDecimal。将mapping Collector 作为参数传递给Collectors.groupingBy() 允许您更改输出映射的值(在你的例子,你把它改成Set&lt;String&gt;)。

    对于 collect() 中的第三个参数,如果我使用 Collectors.toList() 而不是 Collectors.toSet(),我会得到相同的输出类型 Map 吗?

    不,你会得到一个Map&lt;BigDecimal, List&lt;String&gt;&gt;

    【讨论】:

    • 我无法格式化这个抱歉!!如果 grouping by 创建一个 map,那么 groupingby 和 Collectors.toMap() 或 Collectors.Map() 有什么区别? Map mapAliasAddress = Files.lines(Paths.get(fileName)) .map(s -> s.split(",")) .map(sArr -> new EmailAddress(sArr[1], sArr[ 0])) .collect(Collectors.toMap( email -> email.getAlias(), email -> email ));
    • @NoMoreErrors Collectors.toMap 创建一个没有分组的Map,即输入 Stream 的每个元素都映射到输出 Map 的一个 Entry(假设没有重复的键)。 groupingBy 将共享某些属性的输入 Stream 的多个元素映射到输出 Map 的单个条目中。
    • 所以说 Collectors.toMap 和 Collectors.Mapping 完全一样好吗?
    • 我指的是toMap
    • @NoMoreErrors 否,Collectors.mapping() 不能生成 Map(除非它与 groupingBy 结合使用)。例如,如果您有一个List&lt;String&gt;,您可以用Set&lt;Integer&gt; lengths = list.stream ().collect(Collectors.mapping (s-&gt;s.length (),Collectors.toSet())); 生成Set&lt;Integer&gt;,但不能生成Map
    猜你喜欢
    • 2021-05-18
    • 2011-07-30
    • 2011-11-23
    • 2019-08-20
    • 2022-12-04
    相关资源
    最近更新 更多