我有类似以下内容:
public class MyClass {
private Long stackId
private Long questionId
}
例如100的集合,其中stackid可以使用不同的questionId复制。 stackId和questionId之间的一对多关系
是否存在流式,Java 8转换为以下结构的方式:
public class MyOtherClass {
private Long stackId
private Collection<Long> questionIds
}
这将是25个的集合,每个实例具有4个QuestionId的嵌套集合。
输入:
[{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条Stream管道:
Map<Long, List<Long>>
的临时stackId
创建为questionIds
。这是通过 groupingBy(classifier, downstream)
收集器完成的,其中我们根据stackId
进行分类,并将具有相同stackId
的值映射到其questionId
(使用 mapping
),并使用 toList()
收集到列表中。 MyOtherClass
实例,并将其收集到列表中。 假设您有一个构造函数
MyOtherClass(Long stackId, Collection<Long> questionIds)
,则示例代码为: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管道中完成此操作。该库提供了
pairing
和 first
收集器。这样可以配对两个收集器,并对两个收集的结果执行整理器操作:stackId
(根据构造,它们将完全相同)questionId
并收集到列表中。 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();