gpt4 book ai didi

java - Collectors.toMap() 和 Collectors.groupingBy() 收集成 Map 的区别

转载 作者:IT老高 更新时间:2023-10-28 20:48:55 54 4
gpt4 key购买 nike

我想创建一个 Map来自 ListPoints并在映射中使用相同的 parentId 映射列表中的所有条目,例如 Map<Long, List<Point>> .
我用了Collectors.toMap()但它没有编译:

Map<Long, List<Point>> pointByParentId = chargePoints.stream()
.collect(Collectors.toMap(Point::getParentId, c -> c));

最佳答案

TLDR:

收集到Map包含单个键值( Map<MyKey,MyObject> ),使用 Collectors.toMap() .
Collection 到Map包含多个键值( Map<MyKey, List<MyObject>> ),使用 Collectors.groupingBy() .


Collectors.toMap()

通过写作:

chargePoints.stream().collect(Collectors.toMap(Point::getParentId, c -> c));

返回的对象将具有 Map<Long,Point>类型。
Collectors.toMap()您正在使用的功能:

Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper)

它返回一个 Collector结果是Map<K,U>在哪里 KU是传递给方法的两个函数的返回类型。在您的情况下,Point::getParentId是一个 Long 和 c指的是 Point .而Map<Long,Point>返回时 collect()应用于。

而这种行为是相当预期的 Collectors.toMap() javadoc 状态:

returns a Collector that accumulates elements into a Map whose keys and values are the result of applying the provided mapping functions to the input elements.

但如果映射的键包含重复项(根据 Object.equals(Object) ),则 IllegalStateException被抛出
这可能是您的情况,因为您将分组 Point s 根据特定属性:parentId .

如果映射的键可能有重复,您可以使用 toMap(Function, Function, BinaryOperator) 重载,但它不会真正解决您的问题,因为它不会对具有相同 parentId 的元素进行分组.它只会提供一种方法,让两个元素不具有相同的 parentId .


Collectors.groupingBy()

要达到您的要求,您应该使用 Collectors.groupingBy() 行为和方法声明更适合您的需要:

public static <T, K> Collector<T, ?, Map<K, List<T>>>
groupingBy(Function<? super T, ? extends K> classifier)

指定为:

Returns a Collector implementing a "group by" operation on input elements of type T, grouping elements according to a classification function, and returning the results in a Map.

该方法采用 Function .
在您的情况下,Function参数为 Point (Stream 的 type)并且您返回 Point.getParentId()因为您想按 parentId 对元素进行分组值(value)观。

所以你可以写:

Map<Long, List<Point>> pointByParentId = 
chargePoints.stream()
.collect(Collectors.groupingBy( p -> p.getParentId()));

或者使用方法引用:

Map<Long, List<Point>> pointByParentId = 
chargePoints.stream()
.collect(Collectors.groupingBy(Point::getParentId));

Collectors.groupingBy() :走得更远

确实是 groupingBy()收集器比实际示例走得更远。Collectors.groupingBy(Function<? super T, ? extends K> classifier)方法最终只是一种方便的方法来存储收集到的值MapList .
存储 Map 的值除了 List或存储特定计算的结果,groupingBy(Function<? super T, ? extends K> classifier, Collector<? super T, A, D> downstream)你应该感兴趣。

例如:

Map<Long, Set<Point>> pointByParentId = 
chargePoints.stream()
.collect(Collectors.groupingBy(Point::getParentId, toSet()));

所以除了问的问题,你应该考虑groupingBy()作为一种灵活的方式来选择要存储到收集的 Map 中的值, 到底是什么 toMap()不是。

关于java - Collectors.toMap() 和 Collectors.groupingBy() 收集成 Map 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45231351/

54 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com