Streams в Java
Откройте конвейер из списка через stream(), оставьте или измените элементы и в конце напечатайте. В Pipe.java оставьте public класс Pipe, импортируйте java.util.ArrayList, сохраните "oak" и "pine" и вызовите names.stream().filter(n -> n.startsWith("o")).forEach(n -> System.out.println(n));. Скомпилируйте javac Pipe.java и запустите java Pipe. На экране должно быть oak. Вторая демонстрация использует map, чтобы экран показал OAK, затем PINE. Опциональные Records оставьте на следующую страницу. Этот урок — конвейер stream, а не простой forEach по списку и не демо Generics с get(0).
Фильтр: одно подходящее слово
Откройте Pipe.java. Оставьте имя public класса Pipe. Удалите лишние lambda-демо только с Cue, лишние печати Generics из Bin, лишние запуски Program Arguments в Flag и лишние запросы Scanner в Box, если они заслоняют историю streams. Программа не должна ждать ввода и не должна требовать слов запуска.
Добавьте импорт вверху:
import java.util.ArrayList;
Внутри Pipe.main создайте типизированный список из двух слов и запустите stream, который оставляет слова, начинающиеся с o:
ArrayList<String> names = new ArrayList<>();
names.add("oak");
names.add("pine");
names.stream().filter(n -> n.startsWith("o")).forEach(n -> System.out.println(n));
stream() открывает конвейер. filter оставляет элементы, для которых lambda возвращает true. forEach печатает каждый оставшийся элемент. "oak" начинается с o. "pine" — нет. На экране oak.
import java.util.ArrayList;
public class Pipe {
public static void main(String[] args) {
ArrayList<String> names = new ArrayList<>();
names.add("oak");
names.add("pine");
names.stream().filter(n -> n.startsWith("o")).forEach(n -> System.out.println(n));
}
}
В папке, где лежит Pipe.java, выполните javac Pipe.java. Когда скобки и точки с запятой сходятся, javac сам ничего не пишет. Затем запустите java Pipe — не java Pipe.java. Оставьте один public класс, чтобы имя совпадало с Pipe.
Пройдите запуск один раз. Java начинает в Pipe.main. В списке "oak" и "pine". stream() стартует. filter оставляет "oak". forEach печатает oak. Ничего не печатает оба слова. Ничего не вызывает только names.forEach без stream(). Ничего не читает args[0].
Произнесите правило новичка, глядя на экран: stream() открывает трубу; filter выбирает; forEach завершает побочным эффектом печати. Не выдумывайте демо Records на этой странице. Records ждёт следующий опциональный урок. Не убирайте stream() в надежде, что filter повиснет на самом списке в этой учебной форме.
Если вы всё ещё видите oak, затем pine из лишнего файла Cue с forEach, переключитесь на Pipe и оставьте шаг filter. Если javac отвергает stream, убедитесь, что тип списка — ArrayList, а вызов — names.stream().
Map: каждое слово в верхний регистр
Оставьте тот же public класс Pipe. Измените конвейер, чтобы преобразовывать каждое слово вместо фильтрации:
names.stream().map(n -> n.toUpperCase()).forEach(n -> System.out.println(n));
Оставьте в списке и "oak", и "pine". Снова скомпилируйте javac Pipe.java и запустите java Pipe. На экране OAK, затем PINE. map возвращает новое значение для каждого элемента. forEach печатает эти значения по порядку.
import java.util.ArrayList;
public class Pipe {
public static void main(String[] args) {
ArrayList<String> names = new ArrayList<>();
names.add("oak");
names.add("pine");
names.stream().map(n -> n.toUpperCase()).forEach(n -> System.out.println(n));
}
}
Пройдите запуск один раз. Первое сопоставленное значение — OAK. Второе — PINE. Держите две демонстрации как две учебные формы. Сначала докажите, что filter оставляет одно слово. Потом докажите, что map меняет каждое слово. Обе формы делят import, типизированный список, stream() и терминальный forEach.
Если позже в своих опытах свяжете filter и map, порядок важен. На этой странице в каждой демонстрации один промежуточный шаг, чтобы экран оставался читаемым.
Привычки конвейера
Держите шаги по порядку, пока тренируетесь.
📊 Привычки stream для Pipe
| Шаг | Вызов | Проверка новичка |
|---|---|---|
| Старт | names.stream() |
открывает конвейер из списка |
| Оставить часть | filter(n -> ...) |
lambda возвращает true, чтобы оставить |
| Изменить каждый | map(n -> ...) |
lambda возвращает новое значение |
| Завершить печать | forEach(n -> System.out.println(n)) |
терминальный шаг, который печатает |
Пропустить stream() |
у списка нет filter в этой форме |
поставьте stream() перед filter или map |
Streams — не только Lambda и не Records
Урок Lambda учил forEach прямо по списку. Streams ставит stream() первым, чтобы вы могли filter или map до финального forEach. Records позже на опциональной странице введёт компактный тип данных. Не смешивайте все три роли в одном файле новичка сегодня.
oak, оставленный filter, всё ещё элемент списка, текущий по конвейеру. Это не args[0] из Flag. Когда лишний файл Cue печатает каждый элемент без filter, оставьте это историей и сохраните строку stream().filter в Pipe.
Без stream() вызовы filter и map на этой странице — не та учебная форма. Без терминального forEach конвейер не печатает. Держите оба конца трубы вместе, пока тренируете каждую демонстрацию. Синтаксис Records держите вне этой страницы до того урока, даже если вы уже видели заголовок о компактных типах на опциональном пути.
Проверка папки перед Records
После успешной компиляции посмотрите папку. Вы должны видеть Pipe.java и Pipe.class вместе. Отредактируйте исходник, сохраните, выполните javac Pipe.java, затем java Pipe. Устаревший .class может показать старый экран filter, если пропустить компиляцию после переключения на map.
Если javac жалуется на дублирующиеся public классы, оставьте public только у Pipe. Если на демо filter экран показывает и oak, и pine, возможно, нет проверки startsWith("o") — верните lambda filter. Если ничего не печатается, убедитесь, что add выполнился до stream().
Не вставляйте list-only forEach из Cue вместо всего конвейера на этой странице. Не вставляйте get(0) из Bin в Pipe. Опциональная работа streams — это stream плюс один промежуточный шаг плюс forEach.
Перед опциональными Records
Вы можете оставить public класс Pipe, import ArrayList, добавить "oak" и "pine", вызвать names.stream().filter(n -> n.startsWith("o")).forEach(...), увидеть oak, затем вызвать names.stream().map(n -> n.toUpperCase()).forEach(...), увидеть OAK и PINE. Скомпилируйте javac Pipe.java и запустите java Pipe. Таблица отделяет старт, filter, map и финиш. Следующая опциональная страница — Records.
Держите демо Pipe для ясной пары streams. Держите lambda-файлы Cue вне этой страницы, когда тренируете конвейеры. Держите файлы Generics Bin вне этой страницы, когда тренируете конвейеры. Работу с Records вне этой страницы до того урока. Эти привычки — контрольная точка перед продолжением опционального пути. Когда экран filter показывает oak или экран map — OAK и PINE, Streams выполнил работу этого урока, и вы готовы к Records, если продолжите опциональный путь.
Последний проход по папке: один public Pipe, import на месте, типизированный ArrayList<String>, stream() перед filter или map, терминальный forEach, без ожидания Scanner, без слов запуска. Ещё раз выполните javac Pipe.java и java Pipe на демо, которое держите открытым. Если экран всё ещё показывает oak или OAK и PINE, форма Streams прочна, и курс может перейти к опциональным Records на следующей странице. На каждое чтение — одна ясная привычка конвейера, чтобы каждый проход учил той же карте.
🧠 Проверьте Свои Знания
Проверьте Свои Знания
Бросьте себе вызов с помощью этой интерактивной викторины и узнайте, насколько хорошо вы понимаете тему
📝 Инструкции
- Внимательно прочитайте каждый вопрос
- Выберите лучший ответ на каждый вопрос
- Вы можете пересдавать тест столько раз, сколько захотите
- Ваш прогресс будет показан вверху