Карта / Stream API и лямбды / map / filter / collect

map / filter / collect

Stream — это конвейер обработки данных. Представь заводскую сборочную линию: на входе едет сырьё (твоя коллекция), на каждой станции с деталью что-то делают — отсеивают брак, обрабатывают, красят — а в конце готовый продукт складывают в коробку. Stream — ровно это, только для данных: ты описываешь что сделать на каждом шаге, а не пишешь ручной цикл со счётчиками.

было[1, 2, 3, 4, 5]
.filter(> 2)оставили большие
[3, 4, 5]
.map(× 10)преобразовали каждый
[30, 40, 50]
.collect()собрали результат
итогList [30, 40, 50]

Сравни — одна и та же задача «взять имена длиннее 3 букв и сделать их заглавными»:

// Старый способ — цикл
List<String> result = new ArrayList<>();
for (String name : names) {
    if (name.length() > 3) {
        result.add(name.toUpperCase());
    }
}

// Stream — читается как предложение
List<String> result = names.stream()
    .filter(name -> name.length() > 3)
    .map(String::toUpperCase)
    .collect(Collectors.toList());

Stream короче, читается сверху вниз как описание процесса и не меняет исходную коллекцию (создаёт новый результат).

Копнуть глубже

Два вида операций. Цепочка стрима всегда устроена одинаково:

stream() filter map collect промежуточные (копятся) терминальная (запуск)
  • Промежуточные возвращают новый стрим и копятся в цепочку: filter, map, sorted, distinct, limit, skip.
  • Терминальная запускает всю обработку и даёт результат: collect, forEach, count, reduce, anyMatch, findFirst. После неё стрим «израсходован».

Collectors — как собрать результат:

.collect(Collectors.toList());                 // в список
.collect(Collectors.joining(", "));            // склеить в строку
.collect(Collectors.groupingBy(Person::city)); // сгруппировать по городу → Map
🎤 Закрыл тему, если можешь объяснить:
• чем конвейер `filter`/`map`/`collect` удобнее обычного цикла;
• разницу промежуточных и терминальных операций, что такое Collectors (если дошёл до 2-го слоя).