← Назад к вопросам
Как вернуть List из Stream в Stream API
1.0 Junior🔥 231 комментариев
#Stream API и функциональное программирование#Коллекции
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Преобразование Stream в List в Java Stream API
Основной метод: collect()
Главное правило: Stream — это ленивая цепочка трансформаций. Чтобы получить результат, нужно вызвать terminal операцию. Для List используется collect().
1. Базовый способ — toList()
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
// Простой способ (Java 16+)
List<Integer> doubled = numbers.stream()
.map(n -> n * 2)
.toList(); // collect(Collectors.toList())
System.out.println(doubled); // [2, 4, 6, 8, 10]
Что происходит:
.stream()— создаёт Stream из List.map(n -> n * 2)— трансформирует каждый элемент.toList()— terminal операция, собирает результат в List
Результат: immutable List (unmodifiable)
2. Способ с Collectors.toList() (Java 8+)
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
List<Integer> doubled = numbers.stream()
.map(n -> n * 2)
.collect(Collectors.toList());
System.out.println(doubled); // [2, 4, 6, 8, 10]
Отличие от .toList():
.toList()(Java 16+) возвращает immutable ListCollectors.toList()возвращает mutable List (обычно ArrayList)
// .toList() — immutable
List<Integer> list1 = numbers.stream().toList();
list1.add(100); // ❌ UnsupportedOperationException
// Collectors.toList() — mutable
List<Integer> list2 = numbers.stream().collect(Collectors.toList());
list2.add(100); // ✅ Работает
3. Способ с Collectors.toCollection()
// ArrayList
List<Integer> doubled = numbers.stream()
.map(n -> n * 2)
.collect(Collectors.toCollection(ArrayList::new));
// LinkedList
List<Integer> linked = numbers.stream()
.map(n -> n * 2)
.collect(Collectors.toCollection(LinkedList::new));
// Любая другая реализация List
List<Integer> custom = numbers.stream()
.map(n -> n * 2)
.collect(Collectors.toCollection(MyCustomList::new));
Практические примеры
Фильтр + Трансформация
List<User> users = Arrays.asList(
new User(1, "Alice", 25),
new User(2, "Bob", 17),
new User(3, "Charlie", 30)
);
// Получить имена пользователей старше 18
List<String> adultNames = users.stream()
.filter(user -> user.getAge() >= 18)
.map(User::getName)
.toList();
System.out.println(adultNames); // [Alice, Charlie]
Вложенные Stream (flatMap)
public class Order {
private List<Item> items;
public List<Item> getItems() {
return items;
}
}
List<Order> orders = Arrays.asList(
new Order(Arrays.asList(new Item("A"), new Item("B"))),
new Order(Arrays.asList(new Item("C")))
);
// Получить все товары из всех заказов
List<Item> allItems = orders.stream()
.flatMap(order -> order.getItems().stream())
.toList();
System.out.println(allItems); // [A, B, C]
Дублирование элементов
List<Integer> numbers = List.of(1, 2, 3);
// Удвоить каждый элемент
List<Integer> doubled = numbers.stream()
.flatMap(n -> Stream.of(n, n))
.toList();
System.out.println(doubled); // [1, 1, 2, 2, 3, 3]
Удаление дубликатов
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 3);
List<Integer> unique = numbers.stream()
.distinct()
.toList();
System.out.println(unique); // [1, 2, 3]
Сортировка
List<String> words = Arrays.asList("banana", "apple", "cherry");
// По алфавиту
List<String> sorted = words.stream()
.sorted()
.toList();
System.out.println(sorted); // [apple, banana, cherry]
// По длине (обратный порядок)
List<String> sortedByLength = words.stream()
.sorted(Comparator.comparingInt(String::length).reversed())
.toList();
System.out.println(sortedByLength); // [banana, cherry, apple]
Условный сбор
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
// Чётные числа
List<Integer> evens = numbers.stream()
.filter(n -> n % 2 == 0)
.toList();
System.out.println(evens); // [2, 4]
Маппинг объектов
public class User {
private String name;
private int age;
// getters...
}
public record UserDTO(String name, int age) {}
List<User> users = Arrays.asList(
new User("Alice", 25),
new User("Bob", 30)
);
// Преобразовать User в UserDTO
List<UserDTO> dtos = users.stream()
.map(user -> new UserDTO(user.getName(), user.getAge()))
.toList();
System.out.println(dtos); // [UserDTO[name=Alice, age=25], ...]
Сложные примеры
Цепочка операций
List<Integer> result = numbers.stream()
.filter(n -> n > 0) // Только положительные
.map(n -> n * 2) // Удвоить
.filter(n -> n < 20) // Меньше 20
.distinct() // Удалить дубликаты
.sorted() // Отсортировать
.toList();
Группировка данных
List<String> words = Arrays.asList("apple", "apricot", "banana", "blueberry");
// Группировать по первой букве
Map<Character, List<String>> grouped = words.stream()
.collect(Collectors.groupingBy(word -> word.charAt(0)));
System.out.println(grouped);
// {a=[apple, apricot], b=[banana, blueberry]}
// Если нужна List из этих групп
List<List<String>> groupsList = grouped.values()
.stream()
.toList();
Объединение (join)
List<String> words = Arrays.asList("hello", "world", "java");
// Объединить в одну строку
String joined = words.stream()
.collect(Collectors.joining(", "));
System.out.println(joined); // hello, world, java
// Если нужна List с одним элементом
List<String> listWithJoined = words.stream()
.collect(Collectors.joining(", "))
.lines() // Вернёт Stream<String>
.toList(); // Собрать в List
Производительность
Промежуточные операции (lazy)
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
// Эта цепочка НИ ЧТО не делает!
// Это просто определение цепочки
var stream = numbers.stream()
.map(n -> {
System.out.println("Mapping: " + n);
return n * 2;
})
.filter(n -> {
System.out.println("Filtering: " + n);
return n > 4;
});
// Печать начнётся только здесь (terminal операция)
List<Integer> result = stream.toList();
Оптимизация
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
// ❌ Неэффективно — несколько проходов
List<Integer> result = numbers.stream()
.map(n -> n * 2)
.toList();
long sum = numbers.stream()
.map(n -> n * 2)
.mapToLong(n -> n)
.sum();
// ✅ Эффективно — один проход
var numbers2 = numbers.stream()
.map(n -> n * 2)
.toList();
long sum2 = numbers2.stream()
.mapToLong(n -> (long) n)
.sum();
Альтернативы collect()
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
// Получить массив
Integer[] array = numbers.stream()
.toArray(Integer[]::new);
// Получить Set
Set<Integer> set = numbers.stream()
.collect(Collectors.toSet());
// Получить Map
Map<Integer, String> map = numbers.stream()
.collect(Collectors.toMap(
n -> n,
n -> "Number: " + n
));
// Получить Stream (если зачем-то нужно)
Stream<Integer> stream = numbers.stream()
.map(n -> n * 2);
Заключение
.toList()(Java 16+) — самый простой способ, возвращает immutable List.collect(Collectors.toList())— универсальный способ, возвращает mutable List.collect(Collectors.toCollection())— если нужна конкретная реализация (ArrayList, LinkedList)- Stream API — это functional programming подход, мощный инструмент для трансформации данных
- Помни про lazy evaluation — операции выполняются только при вызове terminal операции (toList, collect, etc.)