Как найти первый элемент по условию
Короткий ответ
filter() с findFirst() возвращает Optional — контейнер, в котором результат может быть, а может не быть:
record User(int id, String name) {}
void main() {
var users = List.of(new User(1, "Anna"), new User(2, "Oleg"));
Optional<User> found = users.stream().filter(u -> u.id() == 2).findFirst();
IO.println(found.map(User::name).orElse("not found"));
}Результат:
OlegЕсли не нашли
orElseThrow() выбрасывает исключение, если элемента нет. Это удобно, когда отсутствие — ошибка:
record User(int id, String name) {}
void main() {
var users = List.of(new User(1, "Anna"));
User user = users.stream().filter(u -> u.id() == 5).findFirst()
.orElseThrow(() -> new NoSuchElementException("User 5 not found"));
}Результат:
Exception in thread "main" java.util.NoSuchElementException: User 5 not foundВыполнить действие
ifPresent() выполняет код, только если элемент найден:
void main() {
var words = List.of("tree", "apple", "avocado");
words.stream().filter(w -> w.startsWith("a")).findFirst().ifPresent(w -> IO.println("Found " + w));
}Результат:
Found appleОбычным циклом
Цикл с return делает то же самое и останавливается на первом совпадении:
String firstLong(List<String> words) {
for (String word : words) {
if (word.length() > 4) {
return word;
}
}
return null;
}
void main() {
IO.println(firstLong(List.of("tea", "coffee", "lemonade")));
}Результат:
coffeeЧастая ошибка
Вызывать get() у Optional без проверки. Если элемента нет, будет исключение:
void main() {
var words = List.of("tree");
IO.println(words.stream().filter(w -> w.startsWith("a")).findFirst().get());
}Результат:
Exception in thread "main" java.util.NoSuchElementException: No value presentФункции из этого ответа
- Stream.findFirst() — Возвращает первый элемент потока в виде `Optional`.
- Stream.filter() — Оставляет в потоке только элементы, подходящие под условие.
- Optional.orElse() — Возвращает значение или запасной вариант, если значения нет.
- Optional.ifPresent() — Выполняет действие, только если значение есть.