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

时间:2016-11-27 06:40:09

标签: 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())
                    )
            );

groupingBy和Mapping是否可以互换?他们的不同之处是什么?

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

2 个答案:

答案 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应用于它们。