← Назад к вопросам
Как напишешь команду по сбору ArrayList
1.0 Junior🔥 191 комментариев
#Stream API и функциональное программирование#Коллекции
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Сбор результатов в ArrayList с использованием Stream API
Вопрос о сборе данных в ArrayList — частый в интервью. Он проверяет понимание Stream API и методов сбора данных в Java. За мой опыт я видел множество подходов, от примитивных до оптимизированных.
Традиционный подход (до Java 8)
До появления Stream API сбор в ArrayList выглядел так:
List<String> result = new ArrayList<>();
for (String item : originalList) {
if (item.length() > 3) {
result.add(item.toUpperCase());
}
}
Этот подход работает, но не очень элегантен и требует много кода.
Современный подход со Stream API и collect()
C Java 8+ используется метод collect() с Collectors:
List<String> result = originalList.stream()
.filter(item -> item.length() > 3)
.map(String::toUpperCase)
.collect(Collectors.toList());
Различные способы сбора в список
1. Collectors.toList()
Основной способ сбора в список:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
// Результат: [2, 4]
2. Collectors.toCollection()
Для явного указания типа коллекции:
List<Integer> result = numbers.stream()
.filter(n -> n > 2)
.collect(Collectors.toCollection(ArrayList::new));
// Или с другой коллекцией
LinkedList<Integer> linkedList = numbers.stream()
.filter(n -> n > 2)
.collect(Collectors.toCollection(LinkedList::new));
// Или с TreeSet
NavigableSet<Integer> treeSet = numbers.stream()
.collect(Collectors.toCollection(TreeSet::new));
3. Stream.toList() (Java 16+)
Метод toList() напрямую на Stream — более современный подход:
List<Integer> result = numbers.stream()
.filter(n -> n % 2 == 0)
.toList(); // Возвращает неизменяемый список
Важно: toList() возвращает неизменяемый список (Collections.unmodifiable). Если нужен изменяемый, используйте collect().
4. Сбор с преобразованием (map)
List<String> fruits = Arrays.asList("apple", "banana", "orange");
List<Integer> lengths = fruits.stream()
.map(String::length)
.collect(Collectors.toList());
// Результат: [5, 6, 6]
5. Сбор с фильтрацией и преобразованием
List<String> words = Arrays.asList("hello", "world", "java", "stream");
List<String> result = words.stream()
.filter(word -> word.length() > 4)
.map(String::toUpperCase)
.collect(Collectors.toList());
// Результат: [HELLO, WORLD, STREAM]
Продвинутые техники сбора
1. FlatMap — сбор из вложенных структур
List<List<Integer>> nestedList = Arrays.asList(
Arrays.asList(1, 2, 3),
Arrays.asList(4, 5),
Arrays.asList(6, 7, 8, 9)
);
List<Integer> flatList = nestedList.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
// Результат: [1, 2, 3, 4, 5, 6, 7, 8, 9]
2. Сбор с условной логикой
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<String> result = numbers.stream()
.map(n -> n % 2 == 0 ? "EVEN:" + n : "ODD:" + n)
.collect(Collectors.toList());
// Результат: [ODD:1, EVEN:2, ODD:3, EVEN:4, ...]
3. Сбор от объектов с фильтрацией полей
public class Person {
private String name;
private int age;
// getter'ы...
}
List<Person> people = Arrays.asList(
new Person("John", 25),
new Person("Jane", 30),
new Person("Bob", 28)
);
// Собрать только имена людей старше 25 лет
List<String> names = people.stream()
.filter(p -> p.getAge() > 25)
.map(Person::getName)
.collect(Collectors.toList());
// Результат: [Jane, Bob]
4. Сбор с Skip и Limit
List<Integer> result = numbers.stream()
.skip(2) // Пропустить первые 2 элемента
.limit(3) // Взять следующие 3
.collect(Collectors.toList());
// Результат: [3, 4, 5]
5. Distinct и Sorted при сборе
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 3, 4, 5, 5);
List<Integer> uniqueSorted = numbers.stream()
.distinct()
.sorted()
.collect(Collectors.toList());
// Результат: [1, 2, 3, 4, 5]
// Сортировка в обратном порядке
List<Integer> reverseSorted = numbers.stream()
.distinct()
.sorted(Collections.reverseOrder())
.collect(Collectors.toList());
// Результат: [5, 4, 3, 2, 1]
6. Кастомный Collector
// Сбор в строку с разделителем
String result = fruits.stream()
.collect(Collectors.joining(", "));
// Результат: "apple, banana, orange"
// Сбор в список с префиксом и суффиксом
String prettyResult = fruits.stream()
.collect(Collectors.joining(", ", "[", "]"));
// Результат: "[apple, banana, orange]"
7. Группировка при сборе
Map<Integer, List<Person>> byAge = people.stream()
.collect(Collectors.groupingBy(Person::getAge));
// Результат: {25: [John], 28: [Bob], 30: [Jane]}
8. Условное добавление элементов
List<Integer> result = new ArrayList<>();
result.addAll(
numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList())
);
// Или более элегантно с Optional
List<Integer> filtered = numbers.stream()
.filter(n -> n > 3)
.collect(Collectors.toList());
Производительность: когда использовать какой метод
// Для небольших списков (до 1000 элементов)
List<Integer> small = numbers.stream().collect(Collectors.toList());
// Для больших списков с известной размерностью
List<Integer> large = numbers.stream()
.collect(Collectors.toCollection(() -> new ArrayList<>(numbers.size())));
// Для параллельных потоков
List<Integer> parallel = numbers.parallelStream()
.collect(Collectors.toCollection(ArrayList::new));
Типичные ошибки
// НЕПРАВИЛЬНО: collect() на null stream
Stream<Integer> nullStream = null;
List<Integer> result = nullStream.collect(Collectors.toList()); // NPE
// ПРАВИЛЬНО: проверить перед сбором
List<Integer> result = optional
.map(list -> list.stream()
.collect(Collectors.toList()))
.orElseGet(ArrayList::new);
// НЕПРАВИЛЬНО: забыть про null элементы
List<Integer> withNull = Arrays.asList(1, 2, null, 4);
List<Integer> result = withNull.stream().collect(Collectors.toList()); // [1, 2, null, 4]
// ПРАВИЛЬНО: фильтровать null
List<Integer> filtered = withNull.stream()
.filter(Objects::nonNull)
.collect(Collectors.toList()); // [1, 2, 4]
Заключение
Сбор в ArrayList — базовая операция в Stream API. Основные моменты:
- Используйте collect(Collectors.toList()) для сбора в список
- toList() (Java 16+) удобнее, но возвращает неизменяемый список
- toCollection() дает больше контроля над типом коллекции
- Комбинируйте filter(), map(), flatMap() для сложной логики
- Будьте осторожны с null значениями
- Для больших данных рассмотрите parallelStream()