看看这段代码。
// 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()是一个更受欢迎的选项。
答案 0 :(得分:16)
不,他们完全不同。groupingBy和Mapping是否可以互换?
?
允许您创建groupingBy
,其中键是传递给Map
的第一个参数,值是groupingBy
元素类型的List
。
Stream
会生成Collectors.groupingBy(Item::getPrice)
(假设Map<BigDecimal, List<Item>>
返回Item::getPrice
。将BigDecimal
mapping
作为参数传递给{{1}允许您更改输出映射的值(在您的示例中,您将其更改为Collector
)。
对于collect()中的第三个参数,如果我使用Collectors.toList()而不是Collectors.toSet(),我会得到相同的输出类型Map吗?
不,你会得到Collectors.groupingBy()
。
答案 1 :(得分:14)
不,两者完全不同。
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<BigDecimal,Set<Item>>
(假设getPrice()
返回BigDecimal
)。然而,
items.stream().collect(Collectors.groupingBy(Item::getPrice,
Collectors.mapping(Item::getName, Collectors.toSet())))
返回Map<BigDecimal,Set<String>>
。在收集项目之前,它首先将Item.getName
应用于它们。