如何在Java 8中将列表列表转换为列表?

时间:2014-08-05 19:48:00

标签: java collections java-8

如果我有List<List<Object>>,如何使用Java 8的功能将其转换为包含同一迭代顺序中所有对象的List<Object>

11 个答案:

答案 0 :(得分:738)

您可以使用flatMap将内部列表(将其转换为Streams后)展平为单个Stream,然后将结果收集到列表中:

List<List<Object>> list = ...
List<Object> flat = 
    list.stream()
        .flatMap(List::stream)
        .collect(Collectors.toList());

答案 1 :(得分:40)

flatmap更好,但还有其他方法可以实现相同的

List<List<Object>> listOfList = ... // fill

List<Object> collect = 
      listOfList.stream()
                .collect(ArrayList::new, List::addAll, List::addAll);

答案 2 :(得分:14)

您可以使用Eclipse Collections中的flatCollect()模式。

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的撰稿人。

答案 3 :(得分:14)

flatMap上的Stream方法肯定可以为这些列表压扁,但必须为元素创建Stream个对象,然后为结果创建Stream

您不需要所有Stream个对象。以下是执行任务的简单,简洁的代码。

// listOfLists is a List<List<Object>>.
List<Object> result = new ArrayList<>();
listOfLists.forEach(result::addAll);

由于ListIterable,因此此代码调用the forEach method(Java 8功能),该代码继承自Iterable

  

Iterable的每个元素执行给定操作,直到处理完所有元素或操作引发异常。如果指定了该顺序,则按迭代顺序执行操作。

List的{​​{1}}按顺序返回项目。

对于Iterator,此代码将方法引用(Java 8功能)传递给Java 8之前的方法List.addAll,以按顺序添加内部列表元素。

  

将指定集合中的所有元素按指定集合的​​迭代器(可选操作)返回的顺序追加到此列表的末尾。

答案 4 :(得分:6)

就像@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);
}

答案 5 :(得分:4)

我只想解释另外一个方案,例如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.
 }

我希望这可以在编码时解决某人的问题......

答案 6 :(得分:1)

将列表转换为列表的方法: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]
*/
        }

    }

答案 7 :(得分:1)

对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语句。

答案 8 :(得分:1)

开始,您可以使用 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();

答案 9 :(得分:0)

我们可以为此使用平面地图,请参考以下代码:

 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);

答案 10 :(得分:-1)

List list = map.values().stream().collect(Collectors.toList());

    List<Employee> employees2 = new ArrayList<>();
    
     list.stream().forEach(
             
             n-> employees2.addAll(n));