有没有更优雅的方法从单个流中收集更多列表,然后将它们全部合并?
这是我想出的:
private Set<Long> getAllIds(List<MyClass> fetchedElements) {
Set<Long> myIds = new HashSet<>();
myIds.addAll(fetchedItems.stream().map(MyClass::getBlueId).collect(Collectors.toList()));
myIds.addAll(fetchedItems.stream().map(MyClass::getRedId).collect(Collectors.toList()));
myIds.addAll(fetchedItems.stream().map(MyClass::getGreenId).collect(Collectors.toList()));
return myIds;
}
在我看来,当我查看这三行代码时,因为那里存在代码重复,但是我没有找到一种方法来加入我正在对流进行的不同映射操作。
感谢您的帮助!
最佳答案
使用flatMap
!
fetchedElements.stream()
.flatMap(item -> Stream.of(item.getBlueId(), item.getRedId(), item.getGreenId()))
.collect(Collectors.toSet());
请注意,评估顺序为
BRGBRG
而不是BBRRGG
,当然,由于使用的是Set
,输出顺序是不确定的。我认为这没关系。您可以使此方法更通用:
private Set<Long> getAllIds(List<MyClass> fetchedElements,
List<Function<MyClass, Long>> extractors) {
return fetchedElements.stream()
.flatMap(item -> extractors.stream().map(f -> f.apply(item)))
.collect(Collectors.toSet());
}
致电:
Set<Long> myIds = getAllIds(fetchedElements, List.of(MyClass::getBlueId, MyClass::getRedId, MyClass::getGreenId))
如果需要其他评估顺序,请交换操作顺序:
extractors.stream()
.flatMap(f -> fetchedElements.stream().map(item -> f.apply(item))
.collect(Collectors.toSet()));