Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the first non empty Optional<T> from a list of Optional<T> [duplicate]

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.

like image 206
Pablo Grisafi Avatar asked Jun 17 '15 01:06

Pablo Grisafi


People also ask

What does Optional empty () get () return?

This method returns an Optional object with an empty value.

How do I know if optional is not empty?

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.

How do you find the optional value?

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.

How do you return optional value?

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.


1 Answers

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();
like image 172
bowmore Avatar answered Oct 05 '22 23:10

bowmore