Как включить список списков в список в Java 8?

Если у меня есть List<List<Object>>, как я могу превратить это в List<Object> который содержит все объекты в одном и том же порядке, используя функции Java 8?

Ответ 1

Вы можете использовать flatMap чтобы сгладить внутренние списки (после их преобразования в потоки) в один поток, а затем собрать результат в список:

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

Ответ 2

flatmap лучше, но есть и другие способы добиться того же

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

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

Ответ 3

Метод flatMap в Stream может, конечно, сгладить эти списки для вас, но он должен создать объекты Stream для элемента, а затем Stream для результата.

Вам не нужны все эти объекты Stream. Вот простой и сжатый код для выполнения задачи.

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

Поскольку List is Iterable, этот код вызывает метод forEach (функция Java 8), который унаследован от Iterable.

Выполняет данное действие для каждого элемента Iterable до тех пор, пока все элементы не будут обработаны, или действие не выдает исключение. Действия выполняются в порядке итерации, если указан этот порядок.

И Iterator List возвращает элементы в последовательном порядке.

Для Consumer этот код передается в ссылке метода (функция Java 8) в метод pre-Java 8 List.addAll для добавления элементов внутреннего списка последовательно.

Добавляет все элементы в указанной коллекции в конец этого списка, в том порядке, в котором они возвращаются указанным итератором коллекции (дополнительная операция).

Ответ 4

Вы можете использовать шаблон flatCollect() из Коллекций Eclipse.

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.

Ответ 5

Так же, как @Saravana упомянул:

лучше, но есть другие способы добиться того же

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

Ответ 6

Я просто хочу объяснить еще один сценарий, такой как 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.
 }

Я надеюсь, что это может решить проблему кого-то во время кодирования...

Ответ 7

Метод преобразования Преобразовать список списков в список: 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 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]
*/
        }

    }

Ответ 8

Мы можем использовать 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);

Ответ 9

Расширение ответа 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.