Как преобразовать список списков (List<List<T>>) в плоский список (List<T>) в Java 8?
- > listOfLists = Arrays.asList(
Arrays.asList("a", "b", "c"),
Arrays.asList("d", "e"),
Arrays.asList("f", "g", "h", "i")
);
```
Я хочу получить на выходе:
```java
List
listOfLists.stream()— создаёт поток из вашего исходного списка списков. Тип этого потока —Stream<List<String>>. Каждый элемент потока — это внутренний список (например,["a", "b", "c"])..flatMap(List::stream)— это ключевой момент. МетодflatMapделает две вещи:- Применяет функцию к каждому элементу потока. В нашем случае функция
List::stream(это ссылка на метод) преобразует каждый внутренний список в поток его элементов (Stream<String>). - "Склеивает" (flatten) все полученные потоки в один общий поток.
Визуально это выглядит так: было
[ [a,b,c], [d,e], [f,g,h,i] ], а стало[ a, b, c, d, e, f, g, h, i ].- Применяет функцию к каждому элементу потока. В нашем случае функция
.collect(Collectors.toList())— собирает все элементы получившегося плоского потока обратно в списокList<String>.- Лямбда вместо ссылки на метод: можно написать
.flatMap(list -> list.stream())— это то же самое, что.flatMap(List::stream). - Работа с примитивами: если у вас
List<List<Integer>>, то для лучшей производительности можно использоватьflatMapToInt:listOfLists.stream().flatMapToInt(list -> list.stream().mapToInt(Integer::intValue)).toArray() - Обработка null: если внутри списка могут быть
nullэлементы, используйтеflatMap(list -> list == null ? Stream.empty() : list.stream()). - Сортировка и фильтрация: вы можете комбинировать
flatMapс другими операциями:listOfLists.stream().flatMap(List::stream).filter(s -> s.length() > 1).sorted().collect(Collectors.toList())
Решение с помощью Stream API и flatMap
Ваша задача решается в одну строку с помощью метода flatMap из Stream API. Вот как это выглядит:
List<String> flatList = listOfLists.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
Пошаговое объяснение
Давайте разберём, что здесь происходит:
Полный рабочий пример
import java.util.*;
import java.util.stream.Collectors;
public class FlattenListExample {
public static void main(String[] args) {
List<List<String>> listOfLists = Arrays.asList(
Arrays.asList("a", "b", "c"),
Arrays.asList("d", "e"),
Arrays.asList("f", "g", "h", "i")
);
List<String> flatList = listOfLists.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
System.out.println(flatList); // [a, b, c, d, e, f, g, h, i]
}
}
Варианты и нюансы
Что делать, если нужно сохранить порядок?
Потоки по умолчанию обрабатывают элементы последовательно, если вы не вызываете .parallelStream(). В нашем примере порядок сохранится: сначала все элементы первого списка, затем второго и т.д.
Этот подход — стандартный и самый читаемый способ преобразования списка списков в плоский список в Java 8. Он лаконичен, эффективен и хорошо сочетается с другими операциями Stream API.
<<Альтернативный подход: использование reduce или старый добрый цикл
Хотя flatMap — самый идиоматичный способ, есть и другие варианты. Например, можно использовать reduce для объединения всех списков:
List<String> flatList = listOfLists.stream()
.reduce(new ArrayList<>(), (list1, list2) -> {
list1.addAll(list2);
return list1;
});
Однако этот подход менее эффективен, так как при каждом слиянии создаётся новый список (или модифицируется существующий), и он не рекомендуется для больших объёмов данных.
Если вы не используете Java 8 или предпочитаете более явный код, можно вернуться к классическому решению с вложенными циклами:
List<String> flatList = new ArrayList<>();
for (List<String> innerList : listOfLists) {
flatList.addAll(innerList);
}
Этот код абсолютно прозрачен, легко читается и не требует знания Stream API. Он идеально подходит, если ваша кодовая база ещё не перешла на Java 8 или если вы хотите избежать оверхэда от стримов при работе с очень большими объёмами данных (хотя на практике разница обычно незначительна).
Также стоит упомянуть библиотеку Guava от Google, которая предоставляет утилиту Iterables.concat() для объединения коллекций без создания промежуточных копий.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги