如果我有一个List<List<Object>>,我如何使用Java8的特性将其转换为包含相同迭代顺序的所有对象的List<Object>?
当前回答
扩展Eran的答案,这是最重要的答案,如果你有一堆层次的列表,你可以保持它们的平面映射。
如果需要的话,这还提供了一种方便的过滤方法,可以在你深入图层时进行过滤。
例如:
List<List<List<List<List<List<Object>>>>>> multiLayeredList = ...
List<Object> objectList = multiLayeredList
.stream()
.flatmap(someList1 -> someList1
.stream()
.filter(...Optional...))
.flatmap(someList2 -> someList2
.stream()
.filter(...Optional...))
.flatmap(someList3 -> someList3
.stream()
.filter(...Optional...))
...
.collect(Collectors.toList())
这在SQL中类似于在SELECT语句中包含SELECT语句。
其他回答
从java-16开始,您可以使用Stream#mapMulti
List<Object> result = listOfLists.stream()
.mapMulti((List<Object> list, Consumer<Object> consumer) -> {
list.forEach(consumer::accept);
})
.collect(Collectors.toList());
如果您需要一个不可变的List,您甚至可以使用toList()作为终端操作
List<Object> result = listOfLists.stream()
.mapMulti((List<Object> list, Consumer<Object> consumer) -> {
list.forEach(consumer::accept);
})
.toList();
正如@Saravana提到的:
flatmap更好,但也有其他方法可以实现
listStream.reduce(new ArrayList<>(), (l1, l2) -> {
l1.addAll(l2);
return l1;
});
综上所述,有以下几种方法可以实现这一点:
private <T> List<T> mergeOne(Stream<List<T>> listStream) {
return listStream.flatMap(List::stream).collect(toList());
}
private <T> List<T> mergeTwo(Stream<List<T>> listStream) {
List<T> result = new ArrayList<>();
listStream.forEach(result::addAll);
return result;
}
private <T> List<T> mergeThree(Stream<List<T>> listStream) {
return listStream.reduce(new ArrayList<>(), (l1, l2) -> {
l1.addAll(l2);
return l1;
});
}
private <T> List<T> mergeFour(Stream<List<T>> listStream) {
return listStream.reduce((l1, l2) -> {
List<T> l = new ArrayList<>(l1);
l.addAll(l2);
return l;
}).orElse(new ArrayList<>());
}
private <T> List<T> mergeFive(Stream<List<T>> listStream) {
return listStream.collect(ArrayList::new, List::addAll, List::addAll);
}
扩展Eran的答案,这是最重要的答案,如果你有一堆层次的列表,你可以保持它们的平面映射。
如果需要的话,这还提供了一种方便的过滤方法,可以在你深入图层时进行过滤。
例如:
List<List<List<List<List<List<Object>>>>>> multiLayeredList = ...
List<Object> objectList = multiLayeredList
.stream()
.flatmap(someList1 -> someList1
.stream()
.filter(...Optional...))
.flatmap(someList2 -> someList2
.stream()
.filter(...Optional...))
.flatmap(someList3 -> someList3
.stream()
.filter(...Optional...))
...
.collect(Collectors.toList())
这在SQL中类似于在SELECT语句中包含SELECT语句。
您可以使用flatMap将内部列表(在将其转换为流之后)展平为单个流,然后将结果收集到列表中:
List<List<Object>> list = ...
List<Object> flat =
list.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
我只想再解释一个场景,如列表<文档>,此列表包含其他文档的列表,如列表>Excel>、列表<Word>、列表>PowerPoint>。所以结构是
class A {
List<Documents> documentList;
}
class Documents {
List<Excel> excels;
List<Word> words;
List<PowerPoint> ppt;
}
现在,如果您只想从文档中迭代Excel,请执行以下操作。。
所以代码应该是
List<Documents> documentList = new A().getDocumentList();
//check documentList as not null
Optional<Excel> excelOptional = documentList.stream()
.map(doc -> doc.getExcel())
.flatMap(List::stream).findFirst();
if(excelOptional.isPresent()){
Excel exl = optionalExcel.get();
// now get the value what you want.
}
我希望这可以在编码时解决某人的问题。。。
推荐文章
- 增强的for循环中的Null检查
- c# vs Java Enum(适合c#新手)
- 如何在不强制转换的情况下将double转换为long ?
- for循环和for-each循环在性能上有区别吗?
- 你如何比较两个版本的字符串在Java?
- 为什么在Java和。net中不能修改字符串?
- java.util.Random真的那么随机吗?我怎么能生成52!(阶乘)可能的序列?
- ZoneOffset之间的区别是什么。UTC和ZoneId.of(“UTC”)?
- 类未找到:IntelliJ中的空测试套件
- 将JAR文件添加到Spark作业- Spark -submit
- REST API - dto还是不是?
- JavaFX应用程序图标
- Java:强/软/弱/幻影引用的区别
- 在序列化和反序列化期间JSON属性的不同名称
- 获取Android设备名称