如果我有一个List<List<Object>>
,我如何通过使用Java 8的功能将其转换为包含相同迭代顺序中所有对象的List<Object>
?
您可以使用flatMap
将内部列表(将它们转换为Streams后)展平为单个Stream,然后将结果收集到列表中:
List<List<Object>> list = ...
List<Object> flat =
list.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
flatmap
更好,但还有其他方法可以实现同样的目标
List<List<Object>> listOfList = ... // fill
List<Object> collect =
listOfList.stream()
.collect(ArrayList::new, List::addAll, List::addAll);
flatMap
上的Stream
方法当然可以为这些列表压扁,但它必须为元素创建Stream
对象,然后为结果创建Stream
。
你不需要所有那些Stream
对象。这是执行任务的简单,简洁的代码。
// listOfLists is a List<List<Object>>.
List<Object> result = new ArrayList<>();
listOfLists.forEach(result::addAll);
因为List
是Iterable
,所以这段代码调用the forEach
method(Java 8特性),它继承自Iterable
。
对
Iterable
的每个元素执行给定的操作,直到处理完所有元素或者操作抛出异常为止。如果指定了该顺序,则按迭代顺序执行操作。
而List
的Iterator
按顺序返回项目。
对于Consumer
,此代码将方法引用(Java 8特性)传递给Java 8之前的方法List.addAll
,以顺序添加内部列表元素。
将指定集合中的所有元素按指定集合的迭代器(可选操作)返回的顺序附加到此列表的末尾。
你可以使用flatCollect()
的Eclipse Collections模式。
MutableList<List<Object>> list = Lists.mutable.empty();
MutableList<Object> flat = list.flatCollect(each -> each);
如果你不能从List
更改列表:
List<List<Object>> list = new ArrayList<>();
List<Object> flat = ListAdapter.adapt(list).flatCollect(each -> each);
注意:我是Eclipse Collections的贡献者。
正如@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);
}
我只想解释一个像List<Documents>
这样的场景,这个列表包含了一些其他文档的列表,如List<Excel>
,List<Word>
,List<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.
}
我希望这可以在编码时解决某人的问题...
将列表转换列表转换为列表的方法:ListOfLists.stream()。flatMap(List :: stream).collect(Collectors.toList());例1:
public class ConvertListOfListsToList {
public static void main(String[] args) {
List<String> StringList = Arrays.asList("Protijayi", "Gini", "Gina");
System.out.println(StringList);
List<List<String>> ListOfLists = new ArrayList<>();
ListOfLists.add(StringList);
System.out.println("ListOfLists => " + ListOfLists);
// Now let's do this in Java 8 using FlatMap
List<String> flatMapList = ListOfLists.stream().flatMap(List::stream).collect(Collectors.toList());
System.out.println("FlatList => " + flatMapList);
/*
ListOfLists => [[Protijayi, Gini, Gina]]
FlatList => [Protijayi, Gini, Gina]
*/
}
}
我们可以使用flatmap,请参考下面的代码:
List<Integer> i1= Arrays.asList(1, 2, 3, 4);
List<Integer> i2= Arrays.asList(5, 6, 7, 8);
List<List<Integer>> ii= Arrays.asList(i1, i2);
System.out.println("List<List<Integer>>"+ii);
List<Integer> flat=ii.stream().flatMap(l-> l.stream()).collect(Collectors.toList());
System.out.println("Flattened to List<Integer>"+flat);