How to find the first element matching a condition
Short answer
filter() with findFirst() returns an Optional — a container that may or may not hold a result:
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"));
}Output:
OlegWhen nothing is found
orElseThrow() throws if there is no element. It is convenient when absence is an error:
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"));
}Output:
Exception in thread "main" java.util.NoSuchElementException: User 5 not foundPerforming an action
ifPresent() runs code only if the element is found:
void main() {
var words = List.of("tree", "apple", "avocado");
words.stream().filter(w -> w.startsWith("a")).findFirst().ifPresent(w -> IO.println("Found " + w));
}Output:
Found appleWith a plain loop
A loop with return does the same and stops at the first match:
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")));
}Output:
coffeeCommon mistake
Calling get() on an Optional without checking. If there is no element, it throws:
void main() {
var words = List.of("tree");
IO.println(words.stream().filter(w -> w.startsWith("a")).findFirst().get());
}Output:
Exception in thread "main" java.util.NoSuchElementException: No value presentFunctions used in this recipe
- Stream.findFirst() — Returns the first stream element as an `Optional`.
- Stream.filter() — Keeps only the stream elements that match a condition.
- Optional.orElse() — Returns the value, or a fallback if there is none.
- Optional.ifPresent() — Runs an action only if a value is present.