4 回答
TA贡献1777条经验 获得超3个赞
您可以将toMap收集器与有界方法引用一起使用来获取您需要的内容。另请注意,此解决方案假设您的源容器中没有重复的 A 实例。如果该前提条件成立,则该解决方案将为您提供所需的结果。它看起来是这样的。
Map<A, Collection<B>> resultMap = listofA.stream() .collect(Collectors.toMap(Function.identity(), repo::getListofB);
如果您有重复的 A 元素,那么除了上面给出的功能之外,您还必须使用此合并功能。合并功能可以处理键冲突(如果有)。
Map<A, Collection<B>> resultMap = listofA.stream()
.collect(Collectors.toMap(Function.identity(), repo::getListofB,
(a, b) -> {
a.addAll(b);
return a;
}));这里有一个更简洁的 Java9 方法,它使用flatMapping收集器来处理重复的 A 元素。
Map<A, List<B>> aToBmap = listofA.stream() .collect(Collectors.groupingBy(Function.identity(), Collectors.flatMapping(a -> getListofB(a).stream(), Collectors.toList())));
TA贡献1772条经验 获得超5个赞
这将是直截了当的,
listofA.stream().collect(toMap(Function.identity(), a -> getListofB(a)));
TA贡献1772条经验 获得超8个赞
在这个答案中,我将展示如果列表中有重复A元素会发生什么List<A> listofA。
实际上,如果 中存在重复项listofA,下面的代码将抛出一个IllegalStateException:
Map<A, Collection<B>> resultMap = listofA.stream() .collect(Collectors.toMap( Function.identity(), repo::getListofB);
可能会抛出异常,因为当键中存在冲突时Collectors.toMap不知道如何合并Function.identity()值(即当键映射器函数返回重复项时,如果列表中存在重复元素就会出现这种情况listofA)。
文档中明确指出了这一点:
如果映射的键包含重复项(根据
Object.equals(Object)),则IllegalStateException在执行收集操作时会抛出异常。如果映射的键可能有重复项,请使用toMap(Function, Function, BinaryOperator) 代替。
文档还为我们提供了解决方案:如果存在重复元素,我们需要提供一种合并值的方法。这是一种这样的方式:
Map<A, Collection<B>> resultMap = listofA.stream()
.collect(Collectors.toMap(
Function.identity(),
a -> new ArrayList<>(repo.getListofB(a)),
(left, right) -> {
left.addAll(right);
return left;
});Collectors.toMap它使用接受合并函数作为其第三个参数的重载版本。在合并函数中,Collection.addAll用于将B每个重复A元素的元素添加到每个 的唯一列表中A。
在值映射器函数中,ArrayList创建了一个新值,因此List<B>每个值的原始值A都不会发生变化。另外,当我们创建一个 时Arraylist,我们提前知道它可以被改变(即我们可以稍后向其中添加元素,以防 中存在重复项listofA)。
TA贡献1998条经验 获得超6个赞
要收集一个Map其中键是A未更改的对象,值是对应B对象的列表,可以将toList()收集器替换为以下收集器:
toMap(Function.identity(), a -> repo.getListOfB(a))
第一个参数定义如何从原始对象计算密钥identity():保持流的原始对象不变。
第二个参数定义了如何计算该值,因此这里它仅包含对将 a 转换A为 的列表的方法的调用B。
由于该repo方法仅采用一个参数,因此您还可以通过用方法引用替换 lambda 来提高清晰度:
toMap(Function.identity(), repo::getListOfB)
添加回答
举报
