it-roy-ru.com

Как я могу превратить список списков в список в Java 8?

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

409
Sarah Szabo

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

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

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

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

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

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

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

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

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

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

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

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

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

15
rgettman

Вы можете использовать шаблон 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.

14
Nikhil Nanivadekar

Так же, как @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);
}
6
Hearen

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

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

5
Kushwaha

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

    }
1
Soudipta Dutta