分组对象java 8 [英] grouping objects java 8
问题描述
我有以下内容:
public class MyClass {
private Long stackId
private Long questionId
}
一个100的集合,其中stackid可以是不同的questionIds。它是stackId和questionId之间的一对多关系
A collection of say 100, where the stackid could be duplicate with different questionIds. Its a one to many relationship between stackId and questionId
是否有 streamy ,java 8方式转换为下面的strcuture:
Is there a streamy, java 8 way to convert to the below strcuture :
public class MyOtherClass {
private Long stackId
private Collection<Long> questionIds
}
这是25的集合,每个实例都有一个嵌套的集合4个问题。
Which would be a collection of 25, with each instance having a nested collection of 4 questionIds.
输入:
[{1,100},{1,101},{1,102},{1,103},{2,200},{2,201},{2,202},{1,203}]
输出
[{1, [100,101,102,103]},{2,[200,201,202,203]}]
推荐答案
Stream API的直接方式涉及2流管道:
The straight-forward way with the Stream API involves 2 Stream pipelines:
- 第一个创建临时
Map< Long,List< Long>>
ofstackId
toquestionIds
。这是通过groupingBy(分类器,下游)
收集器,我们根据stackId
和具有相同stackId
的值被映射到他们的questionId
(带有映射
)并使用toList()
。 - 第二个将该地图的每个条目转换为
MyOtherClass
实例并将其收集到列表中。
- The first one creates a temporary
Map<Long, List<Long>>
ofstackId
toquestionIds
. This is done with thegroupingBy(classifier, downstream)
collectors where we classify per thestackId
and values having the samestackId
are mapped to theirquestionId
(withmapping
) and collected into a list withtoList()
. - The second one converts each entry of that map into a
MyOtherClass
instance and collects that into a list.
假设您有一个构造函数 MyOtherClass(Long stackId,Collection< Long> questionIds)
,示例代码woul d be:
Assuming you have a constructor MyOtherClass(Long stackId, Collection<Long> questionIds)
, a sample code would be:
Map<Long, List<Long>> map =
list.stream()
.collect(Collectors.groupingBy(
MyClass::getStackId,
Collectors.mapping(MyClass::getQuestionId, Collectors.toList())
));
List<MyOtherClass> result =
map.entrySet()
.stream()
.map(e -> new MyOtherClass(e.getKey(), e.getValue()))
.collect(Collectors.toList());
使用StreamEx 库,您可以在单个Stream管道中执行此操作。该库提供了 配对
和 第一个
收藏家。这样可以将两个收集器配对并对两个收集的结果执行修整器操作:
Using StreamEx library, you could do that in a single Stream pipeline. This library offers a pairing
and first
collectors. This enables to pair two collectors and perform a finisher operation on the two collected results:
- 第一个只保留第一个
stackId
分组元素(它们都是相同的,通过构造) - 第二个将每个元素映射到它们的
questionId
并收集到列表中。 - 整理器操作只返回
MyOtherClass
的新实例。
- The first one only keeps the first
stackId
of the grouped elements (they will all be the same, by construction) - The second one mapping each element into their
questionId
and collecting into a list. - The finisher operation just returns a new instance of
MyOtherClass
.
示例代码:
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.toList;
import static one.util.streamex.MoreCollectors.first;
import static one.util.streamex.MoreCollectors.pairing;
// ...
Collection<MyOtherClass> result =
StreamEx.of(list)
.groupingBy(
MyClass::getStackId,
pairing(
collectingAndThen(mapping(MyClass::getStackId, first()), Optional::get),
mapping(MyClass::getQuestionId, toList()),
MyOtherClass::new
)
).values();
这篇关于分组对象java 8的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!