I'm moving some code to java8, trying (sometimes forcing myself) to use of streams and lambdas, and I'm not comfortable yet with them.
I have some methods in a class that validate a business object. Every method looks like
Optional<Fail> validate1(BusinessObject bo)
where Fail is an enum that somehow describes the error, and if there's no error the method returns Optional.empty(). I don't need to collect all errors, but return the first error, without executing following validations.
What I'm doing is
//first convert methods to suppliers
Supplier<Optional<Fail>> validate1= () -> validate1(bo);
Supplier<Optional<Fail>> validate2= () -> validate2(bo);
Supplier<Optional<Fail>> validate3= () -> validate3(bo);
//then some stream magic
return Stream.of(validate1, validate2, validate3)
.map(Supplier::get)
.filter(f -> f.isPresent())
.findFirst()
.orElse(Optional.empty()); //without the orElse, no error would return
// Optional(Optional.empty())
// instead of Optional.empty()
It works, it does the job, it does not execute unnecessary methods, it's legible (it'd be more legible if Optional.orElse were named getOrElse, but that's out of my reach). What I'm trying to find out is if this is a reasonable way to do what I want, if this code would be considered 'good style' or 'idiomatic java8', or am I misusing Stream or Optional, or missing something obvious.
The idea of returning the first non-empty Optional or an empty Optional if they are all empty looks general enough to think there is an official way to do it, something in the back of my head is yelling 'Monads!', but my ignorance of Haskell is almost perfect, so I don't know.
This method returns an Optional object with an empty value.
Optional. ofNullable() method of the Optional class, returns a Non-empty Optional if the given object has a value, otherwise it returns an empty Optional. We can check whether the returned Optional value is empty or non-empty using the isPresent() method.
Retrieving the Value From Java 8 Optional Object Using get() Method. The get() method of Optional is simply used to return a value from the Optional object. Suppose the value is not present, then it throws the exception NoSuchElementException.
To return the value of an optional, or a default value if the optional has no value, you can use orElse(other) . Note that I rewrote your code for finding the longest name: you can directly use max(comparator) with a comparator comparing the length of each String.
Optional
is a lot like a Stream
with 0 or 1 elements in it. Yet it doesn't implement Stream
, nor has it a stream()
method (like collections do).
However, it's not that hard converting an Optional<T>
to a Stream<T>
, this Function does it :
public static <T> Function<Optional<? extends T>, Stream<T>> asStream() {
return op -> op.map(Stream::of).orElseGet(Stream::empty);
}
With that method available you can simply use flatMap :
Stream.of(validate1, validate2, validate3)
.map(Supplier::get)
.flatMap(asStream())
.findFirst();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With