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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25147094/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 23:42:52  来源:igfitidea点击:

How can I turn a List of Lists into a List in Java 8?

javacollectionsjava-8

提问by Sarah Szabo

If I have a List<List<Object>>, how can I turn that into a List<Object>that contains all the objects in the same iteration order by using the features of Java 8?

如果我有一个List<List<Object>>,我怎样List<Object>才能通过使用 Java 8 的功能将它转换为包含相同迭代顺序中的所有对象的 ?

采纳答案by Eran

You can use flatMapto flatten the internal lists (after converting them to Streams) into a single Stream, and then collect the result into a list:

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

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

回答by Nikhil Nanivadekar

You can use the flatCollect()pattern from Eclipse Collections.

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

MutableList<List<Object>> list = Lists.mutable.empty();
MutableList<Object> flat = list.flatCollect(each -> each);

If you can't change list from List:

如果您无法从List以下位置更改列表:

List<List<Object>> list = new ArrayList<>();
List<Object> flat = ListAdapter.adapt(list).flatCollect(each -> each);

Note: I am a contributor to Eclipse Collections.

注意:我是 Eclipse Collections 的贡献者。

回答by Saravana

flatmapis better but there are other ways to achieve the same

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

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

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

回答by Kushwaha

I just want to explain one more scenario like List<Documents>, this list contains a few more lists of other documents like List<Excel>, List<Word>, List<PowerPoint>. So the structure is

我只想解释一个场景,比如List<Documents>,这个列表包含更多其他文档的列表,比如List<Excel>, List<Word>, List<PowerPoint>。所以结构是

class A {
  List<Documents> documentList;
}

class Documents {
  List<Excel> excels;
  List<Word> words;
  List<PowerPoint> ppt;
}

Now if you want to iterate Excel only from documents then do something like below..

现在,如果您只想从文档中迭代 Excel,请执行以下操作。

So the code would be

所以代码是

 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.
 }

I hope this can solve someone's issue while coding...

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

回答by rgettman

The flatMapmethod on Streamcan certainly flatten those lists for you, but it must create Streamobjects for element, then a Streamfor the result.

flatMap对方法Stream肯定可以拉平这些清单给你,但它必须创建Stream的元素对象,那么Stream该结果。

You don't need all those Streamobjects. Here is the simple, concise code to perform the task.

您不需要所有这些Stream对象。这是执行任务的简单、简洁的代码。

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

Because a Listis Iterable, this code calls the forEachmethod(Java 8 feature), which is inherited from Iterable.

因为 a Listis Iterable,所以这段代码调用forEach继承自方法(Java 8 特性)Iterable

Performs the given action for each element of the Iterableuntil all elements have been processed or the action throws an exception. Actions are performed in the order of iteration, if that order is specified.

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

And a List's Iteratorreturns items in sequential order.

ListIterator回报顺序的项目。

For the Consumer, this code passes in a method reference (Java 8 feature) to the pre-Java 8 method List.addAllto add the inner list elements sequentially.

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

Appends all of the elements in the specified collection to the end of this list, in the order that they are returned by the specified collection's iterator (optional operation).

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

回答by Hearen

Just as @Saravana mentioned:

正如@Saravana 提到的:

flatmap is better but there are other ways to achieve the same

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

 listStream.reduce(new ArrayList<>(), (l1, l2) -> {
        l1.addAll(l2);
        return l1;
 });

To sum up, there are several ways to achieve the same as follows:

综上所述,有以下几种方式可以实现:

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

回答by Soudipta Dutta

Method to convert a List<List>to List:

方法将转换List<List>List

listOfLists.stream().flatMap(List::stream).collect(Collectors.toList());

See this example:

看这个例子:

public class Example {

    public static void main(String[] args) {
        List<List<String>> listOfLists = Collections.singletonList(Arrays.asList("a", "b", "v"));
        List<String> list = listOfLists.stream().flatMap(List::stream).collect(Collectors.toList());

        System.out.println("listOfLists => " + listOfLists);
        System.out.println("list => " + list);
    }

}       

It prints:

它打印:

listOfLists => [[a, b, c]]
list => [a, b, c]

回答by Pratik Pawar

We can use flatmap for this, please refer below code :

我们可以为此使用 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);

回答by cody.tv.weber

An expansion on Eran's answer that was the top answer, if you have a bunch of layers of lists, you can keep flatmapping them.

Eran 答案的扩展是最佳答案,如果您有一堆列表层,则可以继续对它们进行平面映射。

This also comes with a handy way of filtering as you go down the layers if needed as well.

如果需要,这还提供了一种方便的过滤方式,因为您可以向下层。

So for example:

例如:

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

This is would be similar in SQL to having SELECT statements within SELECT statements.

这在 SQL 中类似于在 SELECT 语句中包含 SELECT 语句。