收集器 (Java) 中的分组依据和映射有什么区别?

2022-09-02 09:01:48

看看这段代码。

// 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())
                    )
            );

分组依据和映射是否可以互换?它们有什么区别?

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


答案 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()))

产生 a(假设返回 a )。然而Map<BigDecimal,Set<Item>>getPrice()BigDecimal

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

返回 .在收集物品之前,它首先适用于它们。Map<BigDecimal,Set<String>>Item.getName


答案 2

分组依据和映射是否可以互换?

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

Collectors.groupingBy(Item::getPrice)将生成一个(假设返回一个 .将 作为参数传递,允许您更改输出映射的值(在您的示例中,将其更改为 )。Map<BigDecimal, List<Item>>Item::getPriceBigDecimalmappingCollectorCollectors.groupingBy()Set<String>

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

不,你会得到一个.Map<BigDecimal, List<String>>


推荐