我有一个简单的嵌套结构:
public static class A {
private List<B> classBList;
// constructor, getters, etc.
}
public static class B {
private int id;
private String name;
// constructor, getters, etc.
}
我想创建一个<Integer,List<A>>
Map,其中类B
id
中的整数字段将是键,输入中包含匹配id
的A
对象将作为值汇总到列表中。输入将是类A
的列表。
例如:
输入:
[classBList=[B{id:1, name:"Hello"}, B{id:1, name:"Hi"}, B{id:1, name:"Bye"}, B{id:1, name:"Yes"}],
classBList=[B{id:2, name:"No"}, B{id:2, name:"Go"}, B{id:2, name:"Yellow"}],
classBList=[B{id:2, name:"Joe"}, B{id:2, name:"Blow"}]]
(a对象列表中的3个元素:classBList中的4个元素用于第一个元素,classBLlist中的3元素用于第二个元素,而classBLList中的2个元素用于第三个元素)
classBList中的每个B
元素将具有相同的id
。
输出:
{Key=1, Value=[ A{classBList=[B{id:1, name:"Hello"}, B{id:1, name:"Hi"}, B{id:1, name:"Bye"}, B{id:1, name:"Yes"}]} ]
{Key=2, Value=[ A{classBList=[B{id:2, name:"No"}, B{id:2, name:"Go"}, B{id:2, name:"Yellow"}, B{id:2, name:"Joe"}, B{id:2, name:"Blow"}]} ]
然而,我在编写允许这种情况发生的lambdas时遇到了麻烦。我尝试了什么:
Map<Integer, List<A>> heyThere = classAListInput.stream()
.collect(Collectors.toMap(
A::getClass,
element -> element.getClassBList().stream()
.map(B::getId)
.collect(Collectors.toList())
));
但这并不能编译,所以不确定语法应该是什么样子。
如果你想知道为什么不改变Map,使其为<Integer,List<B>>,我没有注意到A类中的其他字段,但输出中需要这些字段,这就是为什么A对象的列表将是Map中的值。
4条答案
按热度按时间toiithl61#
似乎您需要用
B
的新列表重新构建A
类的示例。但是,预期输出显示列表中只有一个
A
条目,所有B
都添加到同一A
示例中:因此,假设
A
类中有一个接受List<B>
的all-args构造函数,可以提供以下实现:w80xi6nr2#
如果我正确地理解了这个问题,根据样本数据判断,你有一个
List<List<B>>
作为输入。根据您提供的示例输出,您需要获得
Map<Integer,A>
类型的Map(而不是aMap<Integer,List<A>>
)。这可以通过以下步骤完成:
flatMap()
平坦化数据,即将Stream<List<B>>
转换为Stream<B>
;groupingBy()
将元素按id
分组;A
,这可以通过将收集器collectingAndThen()
和toList()
的组合应用于groupingBy()
下游来完成。这就是它的实现方式:
A link to Online Demo升
v8wbuo2f3#
使用Java 8分组依据:
您可以使用groupingBy功能,如下所示:
1.我使用
flatMap()
将所有数据列表合并为一个列表。1.我用id作为分组元素使用
groupingBy()
,然后在收集数据之前,我用Collectors.mapping()
将数据转换为List<A>
B、 java语言
A、 java语言
测试.java
输出:
smtd7mpg4#
您需要平面Map到某种元组类,如
AbstractMap.SimpleEntry
,这样您就可以并行地对A
和B
进行流处理,然后反转分组: