What is intended behavior of Guava's Optional.or()? - java

A method where I chain optionals does not behave how I thought it would from reading the docs.
Assume all function_n return an Optional<Foo>
public Foo getFooFromService() {
return this.function_1()
.or(this.function_2())
.or(this.function_3())
.or(DEFAULT_VAL)
I thought that for the above code, if function_1 returned a non-absent Optional, then the program would return the inner value of it (the result of .get()) and not do any further computation on function_2 and function_3
My program is for sure doing that additional computation

In order to return a value from getFooFromService, function_1 and three ors have to be executed, meaning that their parameters will be evaluated. function_2 and function_3 will be run under any circumstances.
The option that might be suitable for you is the overloaded version that takes a Supplier which implies lazy evaluation.
public abstract T or(Supplier<? extends T> supplier)
UPDATE
It's a #Beta method (a subject to change), and I find it entirely useless. It resolves a Supplier<? extend T> to T, thus ruins the opportunity of building a chain. Basically, you can't rewrite your snippet to use this method.
UPDATE 1
But you could switch to Java's Optional and write
return function_1()
.orElseGet(() -> function_2()
.orElseGet(() -> function_3()
.orElse(DEFAULT_VAL)));
which isn't that expressive, but working as expected.
My formatting is awful, but you get the idea ;)

Guava "gently recommends" to use Java's Optional
So use Java's Optional to write the rather legible code:
import java.util.*;
class Main {
public static void main(String[] args) {
new Main().getFooFromService();
}
String getFooFromService() {
return this.function_1()
.or(this::function_2) // Requires Java 9
.or(this::function_3) // Requires Java 9
.orElse("DEFAULT_VALUE");
}
Optional<String> function_1() {
System.out.println("function_1 called");
return Optional.empty();
}
Optional<String> function_2() {
System.out.println("function_2 called");
return Optional.of("b");
}
Optional<String> function_3() {
System.out.println("function_3 called");
return Optional.of("c");
}
}
You'll see that in this case, with the given setup, function_1 and function_2 are called, but not function_3.

Related

Is there a clearer way to deal with short-lived optionals?

I love Optional in Java. It has, in one simple class, allowed me to clearly identify return types and arguments which may or may not be available.
One thing that I struggle with is the necessity of assigning it to a short-lived variable which is then inherited into every subsequent scope.
I like to use the simple variable name opt when using optionals like this:
Optional<ThingA> opt = maybeGetThing();
if (opt.isPresent()) {
ThingA usefulVariableName = opt.get();
...
But when I then need a variable name to use in this scope...
void method() {
Optional<ThingA> opt = maybeGetThing();
if (opt.isPresent()) {
ThingA usefulVariableName = opt.get();
usefulVariableName.doA();
usefulVariableName.doB();
usefulVariableName.doC();
// Duplicate local variable opt
Optional<ThingB> opt = usefulVariableName.maybeAnotherThing();
}
}
I can use things like optA and optB and so on. But I wonder if there is another way to write this code without having to enumerate my temporary variables. This just smacks of lazy variable names like a aaaa aaaaaabbb or something.
I don't want to name all of my optionals explicitly like this:
Optional<ThingA> optUsefulVariableName = maybeGetThing();
if (optUsefulVariableName.isPresent()) {
ThingA usefulVariableName = optUsefulVariableName.get();
...
While accurate, it is extremely verbose. I also try to use throwaway names like opt and i to indicate that these are in fact only temporary and should serve no purpose beyond their immediate scope (even though they will be inherited).
UPDATE:
I have seen suggestions for using ifPresent() but I don't see how I can use this for instances where I also need to perform an action if the optional is empty:
void method() {
Optional<ThingA> opt = maybeGetThing();
if (!opt.isPresent()) {
doSomethingOnlyHere();
return;
}
if (opt.isPresent()) {
ThingA usefulVariableName = opt.get();
usefulVariableName.doA();
usefulVariableName.doB();
usefulVariableName.doC();
// Duplicate local variable opt
Optional<ThingB> opt = usefulVariableName.maybeAnotherThing();
}
}
When I try to refactor with ifPresent():
void method() {
// Doesn't handle instance where I need side effects on an empty optional
maybeGetThing().ifPresent(usefulVariableName -> {
...
}
}
The most basic way to eliminate the variable and the need to call Optional#get is to use Optional.ifPresent which calls a function if the Optional has a value.
maybeGetThing().ifPresent(val -> {
// do stuff with side effects here
});
This is still quite a limited way to use Optional, as one of Optionals key purposes is to facilitate programming in a functional style. If you are a beginner this may be a little lost on you, but the idea is to have functions that return something and not functions that rely on side effects. Functions relying on side effects cannot be chained together and are generally harder to reason about.
Technically Optional is something called a Functor (from category theory). It is a wrapper around a value (Whatever T is) and it allows the value to be passed through a series of operations to operate on it and pass it to the next operation until we have what we want, then the chain of operations ends with a terminal (i.e. final) operation. The terminal operation may return the unwrapped value if it exists or it could throw or return some default value if it doesn't.
For Optional it will skip any subsequent operations if the value becomes not present.
There are common operations like map, filter, flatMap (ok that's a Monad operation) and other more java specific operations like Optional#orElse and Optional#orElseThrow.
To refactor your example code you could do this.
void method() {
return maybeGetThing().flatMap(val -> {
// eek side effects
val.doA();
val.doB();
val.doC();
return val.maybeAnotherThing();
});
}
flatMap is a way of converting an Optional of one type to an Optional of another type. If the return value weren't Optional you would use map.
You can see we have eliminated the need for names of return values in favour of naming the parameters of lambda functions. The lambda functions are scoped so you can reuse the names if that's what you want to.
I generally like to provide runnable code, so here is a contrived example of what I mean which is runnable.
import java.util.Optional;
class DummyClass {
private int val = 0;
public void doA(){ val += 1; }
public void doB(){ val += 2; }
public void doC(){ val += 3; }
public Optional<String> maybeAnotherThing(){
return Optional.of(Integer.toString(val));
}
}
public class UseOptional5 {
Optional<DummyClass> maybeGetThing(){
return Optional.of(new DummyClass());
}
String method() {
return maybeGetThing()
// you can put other operations here
.flatMap(val -> {
// eek side effects
val.doA();
val.doB();
val.doC();
return val.maybeAnotherThing();
})
// you can put other operations here too
.orElseThrow(() -> new IllegalArgumentException("fail!!"));
}
public static void main(String args[]) {
UseOptional5 x = new UseOptional5();
System.out.println(x.method());
}
}
Since Java 9 I’d do
void method() {
maybeGetThing().ifPresentOrElse(
usefulVariableName -> {
usefulVariableName.doA();
usefulVariableName.doB();
usefulVariableName.doC();
// No duplicate local variable opt
Optional<ThingB> opt = usefulVariableName.maybeAnotherThing();
},
this::doSomethingOnlyHere
);
}
My rule of thumb is you seldom need or want to use isPresent and/or get, they are low-level. For basic things ifPresent (with f) and ifPresetnOrElse are fine. Others are correct that map and flatMap are very useful too.

How to flip an Option<Try<Foo>> to a Try<Option<Foo>>

I have an Try<Option<Foo>>. I want to flatMap Foo into a Bar, using it using an operation that can fail. It's not a failure if my Option<Foo> is an Option.none(), (and the Try was a success) and in this case there's nothing to do.
So I have code like this, which does work:
Try<Option<Bar>> myFlatMappingFunc(Option<Foo> fooOpt) {
return fooOpt.map(foo -> mappingFunc(foo).map(Option::of) /* ew */)
.getOrElse(Try.success(Option.none()); // double ew
}
Try<Bar> mappingFunc(Foo foo) throws IOException {
// do some mapping schtuff
// Note that I can never return null, and a failure here is a legitimate problem.
// FWIW it's Jackson's readValue(String, Class<?>)
}
I then call it like:
fooOptionTry.flatMap(this::myFlatMappingFunc);
This does work, but it looks really ugly.
Is there a better way to flip the Try and Option around?
Note 1: I actively do not want to call Option.get() and catch that within the Try as it's not semantically correct. I suppose I could recover the NoSuchElementException but that seems even worse, code-wise.
Note 2 (to explain the title): Naively, the obvious thing to do is:
Option<Try<Bar>> myFlatMappingFunc(Option<Foo> fooOpt) {
return fooOpt.map(foo -> mappingFunc(foo));
}
except this has the wrong signature and doesn't let me map with the previous operation that could have failed and also returned a successful lack of value.
When you are working with monads, each monad type combine only with monads of same type. This is usually a problem because the code will come very unreadable.
In the Scala world, there are some solutions, like the OptionT or EitherT transformers, but do this kind of abstractions in Java could be difficult.
The simple solution is to use only one monad type.
For this case, I can think in two alternatives:
transform fooOpt to Try<Foo> using .toTry()
transform both to Either using .toEither()
Functional programmers are usually more comfortable with Either because exceptions will have weird behaviors, instead Either usually not, and both works when you just want to know why and where something failed.
Your example using Either will look like this:
Either<String, Bar> myFlatMappingFunc(Option<Foo> fooOpt) {
Either<String, Foo> fooE = fooOpt.toEither("Foo not found.");
return fooE.flatMap(foo -> mappingFunc(foo));
}
// Look mom!, not "throws IOException" or any unexpected thing!
Either<String, Bar> mappingFunc(Foo foo) {
return Try.of(() -> /*do something dangerous with Foo and return Bar*/)
.toEither().mapLeft(Throwable::getLocalizedMessage);
}
I believe this is simply a sequence function (https://static.javadoc.io/io.vavr/vavr/0.9.2/io/vavr/control/Try.html#sequence-java.lang.Iterable-) that you are looking for:
Try.sequence(optionalTry)
You can combine Try.sequence and headOption functions and create a new transform function with a little better look, in my opinion, also you can use generic types to get a more reusable function :) :
private static <T> Try<Option<T>> transform(Option<Try<T>> optT) {
return Try.sequence(optT.toArray()).map(Traversable::headOption);
}
If I understand correctly, you want to :
keep the first failure if happens
swap the second when mapping to json for an empty option.
Isn t it simpler if you decompose your function in such a way:
public void keepOriginalFailureAndSwapSecondOneToEmpty() {
Try<Option<Foo>> tryOptFoo = null;
Try<Option<Bar>> tryOptBar = tryOptFoo
.flatMap(optFoo ->
tryOptionBar(optFoo)
);
}
private Try<Option<Bar>> tryOptionBar(Option<Foo> optFoo) {
return Try.of(() -> optFoo
.map(foo -> toBar(foo)))
.orElse(success(none())
);
}
Bar toBar(Foo foo) throws RuntimeException {
return null;
}
static class Bar {
}
static class Foo {
}
The solution of throughnothing and durron597 helped me there. This is my groovy test case:
def "checkSomeTry"() {
given:
def ex = new RuntimeException("failure")
Option<Try<String>> test1 = Option.none()
Option<Try<String>> test2 = Option.some(Try.success("success"))
Option<Try<String>> test3 = Option.some(Try.failure(ex))
when:
def actual1 = Try.sequence(test1).map({ t -> t.toOption() })
def actual2 = Try.sequence(test2).map({ t -> t.toOption() })
def actual3 = Try.sequence(test3).map({ t -> t.toOption() })
then:
actual1 == Try.success(Option.none())
actual2 == Try.success(Option.some("success"))
actual3 == Try.failure(ex)
}

Can Java Optional be used for flow control?

I couldn't find a way to do the following with Java's Optional:
if (SOME_OBJECT != null) {
doSomething(SOME_OBJECT);
} else {
doSomethingElse();
}
By using Optional, I don't mean mean replacing SOME_OBJECT == null with Optional.ofNullable(SOME_OBJECT).isPresent(), which a much longer syntax than simply checking if null.
What I would expect is something like:
Optional.ofNullable(SOME_OBJECT)
.ifPresent(this::doSomething)
.orElse(this::doSomethingElse);
I couldn't find an API like the one I just wrote. Does it exist? If so, what is it? If not, why not? :)
The second piece of code looks like an anti-pattern :( Why? Perhaps Java's architects prevented this syntax on purpose...
As mentioned in this Blog Article, Optionals will get a new method in Java 9: void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction). So, with Java, 8 you don't have something like that at the moment.
As BdoubleB97 (Bdubzz) stated, Java 9 will implement Optional#ifPresentOrElse which will take a Consumer<T> which will be applied if the Optional<T> is present, and a Runnable which will be executed if the Optional<T> is empty.
You can either update now to the Java 9 Early Access build, or you can build the method yourself with the following:
public <T> void ifPresentOrElse(Optional<T> optional, Consumer<? super T> action, Runnable emptyAction) {
if (optional.isPresent()) {
action.accept(optional.get());
} else {
emptyAction.run();
}
}
As said Java 8 does not have a construct to do exactly what you want.
I know, it's ugly, far less readable than a simple if/then/else but you can do this:
Optional.ofNullable(someObject)
.map(obj -> {
System.out.println("present");
return obj;
})
.orElseGet(() -> {
System.out.println("not present");
return null;
});
The only side effect is that you have always return something.
Or on the other hand you can handle cleanly the case isPresent().
Optional.ofNullable(someObject).ifPresent(obj -> {
System.out.println("present");
});

What's the most elegant way to combine optionals?

Here's what I've got so far:
Optional<Foo> firstChoice = firstChoice();
Optional<Foo> secondChoice = secondChoice();
return Optional.ofNullable(firstChoice.orElse(secondChoice.orElse(null)));
This strikes me as both hideous and wasteful. If firstChoice is present I am needlessly computing secondChoice.
There's also a more efficient version:
Optional<Foo> firstChoice = firstChoice();
if(firstChoice.isPresent()) {
return firstChoice;
} else {
return secondChoice();
}
Here I can't chain some mapping function to the end without either duplicating the mapper or declaring another local variable. All of this makes the code more complicated than the actual problem being solved.
I'd much rather be writing this:
return firstChoice().alternatively(secondChoice());
However Optional::alternatively obviously doesn't exist. Now what?
Try this:
firstChoice().map(Optional::of)
.orElseGet(this::secondChoice);
The map method gives you an Optional<Optional<Foo>>. Then, the orElseGet method flattens this back to an Optional<Foo>. The secondChoice method will only be evaluated if firstChoice() returns the empty optional.
Maybe something like this:
Optional<String> finalChoice = Optional.ofNullable(firstChoice()
.orElseGet(() -> secondChoice()
.orElseGet(() -> null)));
From: Chaining Optionals in Java 8
You can simply replace that with,
Optional<Foo> firstChoice = firstChoice();
return firstChoice.isPresent()? firstChoice : secondChoice();
The above code won't call unless firstChoice.isPresent() is false.
But you have to be prepare to call both functions to get the desired output. There is no other way to escape the checking.
Best case is First choice returning true.
Worst case will be First choice returning false, hence another method
call for second choice.
Here's the generalization of #marstran solution for any number of optionals:
#SafeVarargs
public static <T> Optional<T> selectOptional(Supplier<Optional<T>>... optionals) {
return Arrays.stream(optionals)
.reduce((s1, s2) -> () -> s1.get().map(Optional::of).orElseGet(s2))
.orElse(Optional::empty).get();
}
Test:
public static Optional<String> first() {
System.out.println("foo called");
return Optional.empty();
}
public static Optional<String> second() {
System.out.println("bar called");
return Optional.of("bar");
}
public static Optional<String> third() {
System.out.println("baz called");
return Optional.of("baz");
}
public static void main(String[] args) {
System.out.println(selectOptional(() -> first(), () -> second(), () -> third()));
}
Output:
foo called
bar called
Optional[bar]
I was frustrated enough by the fact that this wasn't supported in java 8, that I switched back to guava's optionals which have or:
public abstract Optional<T> or(Optional<? extends T> secondChoice)
Returns this Optional if it has a value present; secondChoice otherwise.
Java 9 added the Optional.or​(Supplier<? extends Optional<? extends T>> supplier) method for this sort of situation.
Given methods firstChoice() and secondChoice() that each return Optional<Foo>, the following one-liner uses Optional.or to achieve the desired result:
return firstChoice().or(this::secondChoice);
This approach has the added benefit of only computing secondChoice when firstChoice is empty.
Lazy computations and arbitrary number of Optional elements
Stream.<Supplier<Optional<Foo>>>of(
this::firstChoice,
this::secondChoice
).map(
Supplier::get
).filter(
Optional::isPresent
).findFirst(
).orElseGet(
Optional::empty
);
Here is a way which works for arbitrary number of Optional's based in a stream API:
return Arrays.asList(firstChoice, secondChoice).stream()
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst().orElse(null);
It's not the shortest one. But more plain and understandable.
Another way is to use firstNonNull() from Guava of commons-lang if you are already using one of those libraries:
firstNonNull(firstChoice.orElse(null), secondChoice.orElse(null));

Using Java 8's Optional with Stream::flatMap

The new Java 8 stream framework and friends make for some very concise Java code, but I have come across a seemingly-simple situation that is tricky to do concisely.
Consider a List<Thing> things and method Optional<Other> resolve(Thing thing). I want to map the Things to Optional<Other>s and get the first Other.
The obvious solution would be to use things.stream().flatMap(this::resolve).findFirst(), but flatMap requires that you return a stream, and Optional doesn't have a stream() method (or is it a Collection or provide a method to convert it to or view it as a Collection).
The best I can come up with is this:
things.stream()
.map(this::resolve)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
But that seems awfully long-winded for what seems like a very common case.
Anyone have a better idea?
Java 9
Optional.stream has been added to JDK 9. This enables you to do the following, without the need of any helper method:
Optional<Other> result =
things.stream()
.map(this::resolve)
.flatMap(Optional::stream)
.findFirst();
Java 8
Yes, this was a small hole in the API, in that it's somewhat inconvenient to turn an Optional<T> into a zero-or-one length Stream<T>. You could do this:
Optional<Other> result =
things.stream()
.map(this::resolve)
.flatMap(o -> o.isPresent() ? Stream.of(o.get()) : Stream.empty())
.findFirst();
Having the ternary operator inside the flatMap is a bit cumbersome, though, so it might be better to write a little helper function to do this:
/**
* Turns an Optional<T> into a Stream<T> of length zero or one depending upon
* whether a value is present.
*/
static <T> Stream<T> streamopt(Optional<T> opt) {
if (opt.isPresent())
return Stream.of(opt.get());
else
return Stream.empty();
}
Optional<Other> result =
things.stream()
.flatMap(t -> streamopt(resolve(t)))
.findFirst();
Here, I've inlined the call to resolve() instead of having a separate map() operation, but this is a matter of taste.
I'm adding this second answer based on a proposed edit by user srborlongan to my other answer. I think the technique proposed was interesting, but it wasn't really suitable as an edit to my answer. Others agreed and the proposed edit was voted down. (I wasn't one of the voters.) The technique has merit, though. It would have been best if srborlongan had posted his/her own answer. This hasn't happened yet, and I didn't want the technique to be lost in the mists of the StackOverflow rejected edit history, so I decided to surface it as a separate answer myself.
Basically the technique is to use some of the Optional methods in a clever way to avoid having to use a ternary operator (? :) or an if/else statement.
My inline example would be rewritten this way:
Optional<Other> result =
things.stream()
.map(this::resolve)
.flatMap(o -> o.map(Stream::of).orElseGet(Stream::empty))
.findFirst();
An my example that uses a helper method would be rewritten this way:
/**
* Turns an Optional<T> into a Stream<T> of length zero or one depending upon
* whether a value is present.
*/
static <T> Stream<T> streamopt(Optional<T> opt) {
return opt.map(Stream::of)
.orElseGet(Stream::empty);
}
Optional<Other> result =
things.stream()
.flatMap(t -> streamopt(resolve(t)))
.findFirst();
COMMENTARY
Let's compare the original vs modified versions directly:
// original
.flatMap(o -> o.isPresent() ? Stream.of(o.get()) : Stream.empty())
// modified
.flatMap(o -> o.map(Stream::of).orElseGet(Stream::empty))
The original is a straightforward if workmanlike approach: we get an Optional<Other>; if it has a value, we return a stream containing that value, and if it has no value, we return an empty stream. Pretty simple and easy to explain.
The modification is clever and has the advantage that it avoids conditionals. (I know that some people dislike the ternary operator. If misused it can indeed make code hard to understand.) However, sometimes things can be too clever. The modified code also starts off with an Optional<Other>. Then it calls Optional.map which is defined as follows:
If a value is present, apply the provided mapping function to it, and if the result is non-null, return an Optional describing the result. Otherwise return an empty Optional.
The map(Stream::of) call returns an Optional<Stream<Other>>. If a value was present in the input Optional, the returned Optional contains a Stream that contains the single Other result. But if the value was not present, the result is an empty Optional.
Next, the call to orElseGet(Stream::empty) returns a value of type Stream<Other>. If its input value is present, it gets the value, which is the single-element Stream<Other>. Otherwise (if the input value is absent) it returns an empty Stream<Other>. So the result is correct, the same as the original conditional code.
In the comments discussing on my answer, regarding the rejected edit, I had described this technique as "more concise but also more obscure". I stand by this. It took me a while to figure out what it was doing, and it also took me a while to write up the above description of what it was doing. The key subtlety is the transformation from Optional<Other> to Optional<Stream<Other>>. Once you grok this it makes sense, but it wasn't obvious to me.
I'll acknowledge, though, that things that are initially obscure can become idiomatic over time. It might be that this technique ends up being the best way in practice, at least until Optional.stream gets added (if it ever does).
UPDATE: Optional.stream has been added to JDK 9.
You cannot do it more concise as you are already doing.
You claim that you do not want .filter(Optional::isPresent) and .map(Optional::get).
This has been resolved by the method #StuartMarks describes, however as a result you now map it to an Optional<T>, so now you need to use .flatMap(this::streamopt) and a get() in the end.
So it still consists of two statements and you can now get exceptions with the new method! Because, what if every optional is empty? Then the findFirst() will return an empty optional and your get() will fail!
So what you have:
things.stream()
.map(this::resolve)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
is actually the best way to accomplish what you want, and that is you want to save the result as a T, not as an Optional<T>.
I took the liberty of creating a CustomOptional<T> class that wraps the Optional<T> and provides an extra method, flatStream(). Note that you cannot extend Optional<T>:
class CustomOptional<T> {
private final Optional<T> optional;
private CustomOptional() {
this.optional = Optional.empty();
}
private CustomOptional(final T value) {
this.optional = Optional.of(value);
}
private CustomOptional(final Optional<T> optional) {
this.optional = optional;
}
public Optional<T> getOptional() {
return optional;
}
public static <T> CustomOptional<T> empty() {
return new CustomOptional<>();
}
public static <T> CustomOptional<T> of(final T value) {
return new CustomOptional<>(value);
}
public static <T> CustomOptional<T> ofNullable(final T value) {
return (value == null) ? empty() : of(value);
}
public T get() {
return optional.get();
}
public boolean isPresent() {
return optional.isPresent();
}
public void ifPresent(final Consumer<? super T> consumer) {
optional.ifPresent(consumer);
}
public CustomOptional<T> filter(final Predicate<? super T> predicate) {
return new CustomOptional<>(optional.filter(predicate));
}
public <U> CustomOptional<U> map(final Function<? super T, ? extends U> mapper) {
return new CustomOptional<>(optional.map(mapper));
}
public <U> CustomOptional<U> flatMap(final Function<? super T, ? extends CustomOptional<U>> mapper) {
return new CustomOptional<>(optional.flatMap(mapper.andThen(cu -> cu.getOptional())));
}
public T orElse(final T other) {
return optional.orElse(other);
}
public T orElseGet(final Supplier<? extends T> other) {
return optional.orElseGet(other);
}
public <X extends Throwable> T orElseThrow(final Supplier<? extends X> exceptionSuppier) throws X {
return optional.orElseThrow(exceptionSuppier);
}
public Stream<T> flatStream() {
if (!optional.isPresent()) {
return Stream.empty();
}
return Stream.of(get());
}
public T getTOrNull() {
if (!optional.isPresent()) {
return null;
}
return get();
}
#Override
public boolean equals(final Object obj) {
return optional.equals(obj);
}
#Override
public int hashCode() {
return optional.hashCode();
}
#Override
public String toString() {
return optional.toString();
}
}
You will see that I added flatStream(), as here:
public Stream<T> flatStream() {
if (!optional.isPresent()) {
return Stream.empty();
}
return Stream.of(get());
}
Used as:
String result = Stream.of("a", "b", "c", "de", "fg", "hij")
.map(this::resolve)
.flatMap(CustomOptional::flatStream)
.findFirst()
.get();
You still will need to return a Stream<T> here, as you cannot return T, because if !optional.isPresent(), then T == null if you declare it such, but then your .flatMap(CustomOptional::flatStream) would attempt to add null to a stream and that is not possible.
As example:
public T getTOrNull() {
if (!optional.isPresent()) {
return null;
}
return get();
}
Used as:
String result = Stream.of("a", "b", "c", "de", "fg", "hij")
.map(this::resolve)
.map(CustomOptional::getTOrNull)
.findFirst()
.get();
Will now throw a NullPointerException inside the stream operations.
Conclusion
The method you used, is actually the best method.
A slightly shorter version using reduce:
things.stream()
.map(this::resolve)
.reduce(Optional.empty(), (a, b) -> a.isPresent() ? a : b );
You could also move the reduce function to a static utility method and then it becomes:
.reduce(Optional.empty(), Util::firstPresent );
As my previous answer appeared not to be very popular, I will give this another go.
A short answer:
You are mostly on a right track. The shortest code to get to your desired output I could come up with is this:
things.stream()
.map(this::resolve)
.filter(Optional::isPresent)
.findFirst()
.flatMap( Function.identity() );
This will fit all your requirements:
It will find first response that resolves to a nonempty Optional<Result>
It calls this::resolve lazily as needed
this::resolve will not be called after first non-empty result
It will return Optional<Result>
Longer answer
The only modification compared to OP initial version was that I removed .map(Optional::get) before call to .findFirst() and added .flatMap(o -> o) as the last call in the chain.
This has a nice effect of getting rid of the double-Optional, whenever stream finds an actual result.
You can't really go any shorter than this in Java.
The alternative snippet of code using the more conventional for loop technique is going to be about same number of lines of code and have more or less same order and number of operations you need to perform:
Calling this.resolve,
filtering based on Optional.isPresent
returning the result and
some way of dealing with negative result (when nothing was found)
Just to prove that my solution works as advertised, I wrote a small test program:
public class StackOverflow {
public static void main( String... args ) {
try {
final int integer = Stream.of( args )
.peek( s -> System.out.println( "Looking at " + s ) )
.map( StackOverflow::resolve )
.filter( Optional::isPresent )
.findFirst()
.flatMap( o -> o )
.orElseThrow( NoSuchElementException::new )
.intValue();
System.out.println( "First integer found is " + integer );
}
catch ( NoSuchElementException e ) {
System.out.println( "No integers provided!" );
}
}
private static Optional<Integer> resolve( String string ) {
try {
return Optional.of( Integer.valueOf( string ) );
}
catch ( NumberFormatException e )
{
System.out.println( '"' + string + '"' + " is not an integer");
return Optional.empty();
}
}
}
(It does have few extra lines for debugging and verifying that only as many calls to resolve as needed...)
Executing this on a command line, I got the following results:
$ java StackOferflow a b 3 c 4
Looking at a
"a" is not an integer
Looking at b
"b" is not an integer
Looking at 3
First integer found is 3
Late to the party, but what about
things.stream()
.map(this::resolve)
.filter(Optional::isPresent)
.findFirst().get();
You can get rid of the last get() if you create a util method to convert optional to stream manually:
things.stream()
.map(this::resolve)
.flatMap(Util::optionalToStream)
.findFirst();
If you return stream right away from your resolve function, you save one more line.
I'd like to promote factory methods for creating helpers for functional APIs:
Optional<R> result = things.stream()
.flatMap(streamopt(this::resolve))
.findFirst();
The factory method:
<T, R> Function<T, Stream<R>> streamopt(Function<T, Optional<R>> f) {
return f.andThen(Optional::stream); // or the J8 alternative:
// return t -> f.apply(t).map(Stream::of).orElseGet(Stream::empty);
}
Reasoning:
As with method references in general, compared to lambda expressions, you can't accidentaly capture a variable from the accessible scope, like:
t -> streamopt(resolve(o))
It's composable, you can e.g. call Function::andThen on the factory method result:
streamopt(this::resolve).andThen(...)
Whereas in the case of a lambda, you'd need to cast it first:
((Function<T, Stream<R>>) t -> streamopt(resolve(t))).andThen(...)
If you're stuck with Java 8 but have access to Guava 21.0 or newer, you can use Streams.stream to convert an optional into a stream.
Thus, given
import com.google.common.collect.Streams;
you can write
Optional<Other> result =
things.stream()
.map(this::resolve)
.flatMap(Streams::stream)
.findFirst();
If you don't mind to use a third party library you may use Javaslang. It is like Scala, but implemented in Java.
It comes with a complete immutable collection library that is very similar to that known from Scala. These collections replace Java's collections and Java 8's Stream. It also has its own implementation of Option.
import javaslang.collection.Stream;
import javaslang.control.Option;
Stream<Option<String>> options = Stream.of(Option.some("foo"), Option.none(), Option.some("bar"));
// = Stream("foo", "bar")
Stream<String> strings = options.flatMap(o -> o);
Here is a solution for the example of the initial question:
import javaslang.collection.Stream;
import javaslang.control.Option;
public class Test {
void run() {
// = Stream(Thing(1), Thing(2), Thing(3))
Stream<Thing> things = Stream.of(new Thing(1), new Thing(2), new Thing(3));
// = Some(Other(2))
Option<Other> others = things.flatMap(this::resolve).headOption();
}
Option<Other> resolve(Thing thing) {
Other other = (thing.i % 2 == 0) ? new Other(i + "") : null;
return Option.of(other);
}
}
class Thing {
final int i;
Thing(int i) { this.i = i; }
public String toString() { return "Thing(" + i + ")"; }
}
class Other {
final String s;
Other(String s) { this.s = s; }
public String toString() { return "Other(" + s + ")"; }
}
Disclaimer: I'm the creator of Javaslang.
Null is supported by the Stream provided My library abacus-common. Here is code:
Stream.of(things).map(e -> resolve(e).orNull()).skipNull().first();
What about that?
private static List<String> extractString(List<Optional<String>> list) {
List<String> result = new ArrayList<>();
list.forEach(element -> element.ifPresent(result::add));
return result;
}
https://stackoverflow.com/a/58281000/3477539
Most likely You are doing it wrong.
Java 8 Optional is not meant to be used in this manner. It is usually only reserved for terminal stream operations that may or may not return a value, like find for example.
In your case it might be better to first try to find a cheap way to filter out those items that are resolvable and then get the first item as an optional and resolve it as a last operation. Better yet - instead of filtering, find the first resolvable item and resolve it.
things.filter(Thing::isResolvable)
.findFirst()
.flatMap(this::resolve)
.get();
Rule of thumb is that you should strive to reduce number of items in the stream before you transform them to something else. YMMV of course.

Categories

Resources