I have an Optional<LocalDate>
object and a Stream
of other dates.
Stream<LocalDate> dates = ...;
Optional<LocalDate> dateOptional = ...;
I would like to filter out all dates which are after the optional. If the optional is not present, the filter should not do anything.
I have written the Predicate
like this:
Predicate<LocalDate> predicate = date -> !dateOptional.isPresent() || !date.isAfter(dateOptional.get());
Stream<LocalDate> filteredStream = dates.filter(predicate);
I would like to avoid using isPresent()
and get()
. Is there a more functional way of writing the same logic? I am using Java 8.
The point is that the Predicate<T>
must return an expression that always results in a boolean
.
Since the Localdate::isAfter
returns boolean
you can use is with the advantage of Optional
inside the Predicate<LocalDate>
and result in boolean
:
Optional<LocalDate> dateOptional = ...;
// Together Predicate<LocalDate>
Predicate<LocalDate> predicate = date -> dateOptional // .. Optional<LocalDate>
.map(d -> !date.isAfter(d)) // .. Optional<Boolean>
.orElse(true); // .. Boolean
Stream<LocalDate> filteredStream = dates.filter(predicate);
Don't forget, the Stream<LocalDate>
remains open until the terminal operation.
Edit: Thanks to @Holger: The whole predicate
might be optimized to avoid repetitively and unnecessary calls:
Predicate<LocalDate> predicate = dateOptional // Optional<LocalDate>
.<Predicate<LocalDate>>map(d -> date -> !date.isAfter(d)) // Optional<Predicate<LocalDate>>
.orElse(date -> true); // Predicate<LocalDate>