收集器(Java)中的groupingby和mapping之间有什么区别?

NoM*_*ors 14 java java-8 java-stream collectors

看看这段代码.

// 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())
                    )
            );
Run Code Online (Sandbox Code Playgroud)

groupingBy和Mapping是否可以互换?他们的区别是什么?

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

Era*_*ran 17

groupingBy和Mapping是否可以互换?

不,他们完全不同.groupingBy让你创建一个Map键,其中键是传递给的第一个参数groupingBy,值是List元素类型的一个Stream.

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

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

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

  • @NoMoreErrors`Collectors.toMap`创建一个没有分组的`Map`,即输入Stream的每个元素都映射到输出Map的Entry(假设没有重复的键).`groupingBy`将输入Stream的多个元素映射到输出Map的单个Entry中. (2认同)
  • @NoMoreErrors不,`Collectors.mapping()`不能生成`Map`(除非它与`groupingBy`结合使用).例如,如果你有一个`List <String>`,你可以使用`Set <Integer> lengths = list.stream().collect生成一个`Set <Integer>`(Collectors.mapping(s-> s.length) (),Collectors.toSet()));`,但不是`Map`. (2认同)

Hoo*_*pje 15

不,两者完全不同.

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

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

items.stream().map(f).collect(c);
items.stream().collect(Collectors.mapping(f, c));
Run Code Online (Sandbox Code Playgroud)

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

items.stream().collect(Collectors.groupingBy(Item::getPrice, Collectors.toSet()))
Run Code Online (Sandbox Code Playgroud)

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

items.stream().collect(Collectors.groupingBy(Item::getPrice,
    Collectors.mapping(Item::getName, Collectors.toSet())))
Run Code Online (Sandbox Code Playgroud)

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