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");
});
Related
I have a function returning an Either<MyError, String> (function2) , which result depends on another function returning another Either<MyError, SomethingElse> (function1)
Both functions rely on a Try block that could fail, and I want to compose those two first function to create a "handle" which will be the main function of my class.
There are basically 3 scenarios possible :
function1 fails : I want handle to return the error given by function1
function1 succeeds and function2 fails : function2 must return its own error then returned by handle
both functions work : handle must return the String
Here is my current code :
private Either<MyError, Path> getPath(Arg arg) { // function 1
return Try.of(() -> //some code that can fail)
.toEither().mapLeft(e -> new MyError("Error message for function1", e));
}
private Either<MyError, String> getContent(Path path) { // function 2
return Try.of(() -> //some code that can fail)
.toEither().mapLeft(e -> new MyError("Error message for function2", e));
}
public Either<MyError, String> handle(Arg arg) {
return Either.right(arg)
.map(this::getPath)
.map(this::getContent);
}
Everything works except the Handle function, I think that my problem might be related to the use of Either::map function, that might not be the thing for my case.
Any thought about this ?
Also, sorry if the answer seems obvious, i am quite new to functionnal programming and vavr.
The method that could help to make this work would be flatMap.
So if you use flatMap instead of map, the handle method will become something like:
public Either<MyError, String> handle(Arg arg) {
return Either.<MyError, Arg>right(arg)
.flatMap(this::getPath)
.flatMap(this::getContent);
}
The scenarios you mentioned are all covered with this flatMap method.
See the Either.flatMap documentation for the official docs about it.
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.
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)
}
Java 8 presents Optional class.
Before (Java 7):
Order order = orderBean.getOrder(id);
if (order != null) {
order.setStatus(true);
pm.persist(order);
} else {
logger.warning("Order is null");
}
So on Java 8 style:
Optional<Order> optional = Optional.ofNullable(orderBean.getOrder(id));
optional.ifPresent( s -> {
s.setStatus(true);
pm.persist(s);
//Can we return from method in this place (not from lambda) ???
});
//So if return take place above, we can avoid if (!optional.isPresent) check
if (!optional.isPresent) {
logger.warning("Order is null");
}
Is it correct to use Optional in this case? Can anyone propose a more convenient way in Java 8 style?
Unfortunately, the ifPresentOrElse method you're looking for will be added only in JDK-9. Currently you can write your own static method in your project:
public static <T> void ifPresentOrElse(Optional<T> optional,
Consumer<? super T> action, Runnable emptyAction) {
if (optional.isPresent()) {
action.accept(optional.get());
} else {
emptyAction.run();
}
}
And use like this:
Optional<Order> optional = Optional.ofNullable(orderBean.getOrder(id));
ifPresentOrElse(optional, s -> {
s.setStatus(true);
pm.persist(s);
}, () -> logger.warning("Order is null"));
In Java-9 it would be easier:
optional.ifPresentOrElse(s -> {
s.setStatus(true);
pm.persist(s);
}, () -> logger.warning("Order is null"));
//Can we return from method in this plase (not from lambda) ???
Lambdas do not implement "non-local return" semantics, therefore the answer is no.
Generally, since you need side-effectful action in both the case where the value is present and not, a branching point in the code is essential—whether you wrap it in some fancy API or not. Also, FP generally helps improve referentially transparent transformations (i.e., code built around pure functions) and not side effects, so you won't find much benefit by going through the Optional API.
You have already seen this many times yourself, of that I'm sure:
public SomeObject findSomeObject(Arguments args) {
SomeObject so = queryFirstSource(args); // the most likely source first, hopefully
if (so != null) return so;
so = querySecondSource(args); // a source less likely than the first, hopefully
if (so != null) return so;
so = queryThirdSource(args); // a source less likely than the previous, hopefully
if (so != null) return so;
// and so on
}
We have different sources where an object we search could be. As a more vivid example we could image that we first check if a userid is in a list of privileged users. If not we check if the userid is in the list of allowed users. Else we return null. (It's not the best example but I hope it's a vivid-enough one.)
Guava offers us some helpers that could beautify that code above:
public SomeObject findSomeObject(Arguments args) {
// if there are only two objects
return com.google.common.base.Objects.firstNonNull(queryFirstSource(args), querySecondSource(args));
// or else
return com.google.common.collect.Iterables.find(
Arrays.asList(
queryFirstSource(args)
, querySecondSource(args)
, queryThirdSource(args)
// , ...
)
, com.google.common.base.Predicates.notNull()
);
}
But, as the more experienced among us will have already seen, this may perform bad if the lookups (i.e. queryXXXXSource(args)) take a certain amount of time. This is because we now query all sources first and then pass the results to the method that finds the first among those results which is not null.
In contrast to the first example, where the next source is only evaluated when the former does not return something, this second solution may look better at first but could perform much worse.
Here's where we come to my actual question and to where I suggest something of that I hope someone has already implemented the base of it or of that someone might propose a even smarted solution.
In plain English: Has someone already implemented such a defferedFirstNonNull (see below) or something similar? Is there an easy plain-Java solution to achieve this with the new Stream framework? Can you propose another elegant solution that achieves the same result?
Rules: Java 8 is allowed as well as active maintained and well-known third party libraries like Google's Guava or Apache's Commons Lang with Apache License or similar (No GPL!).
The proposed solution:
public SomeObject findSomeObject(Arguments args) {
return Helper.deferredFirstNonNull(
Arrays.asList(
args -> queryFirstSource(args)
, args -> querySourceSource(args)
, args -> queryThirdSource(args)
)
, x -> x != null
)
}
So the method defferedFirstNonNull would evaluate each lambda expression after another and as soon as the predicate (x -> x != null) is true (i.e. we found a match) the method would return the result immediately and would not query any further source.
PS: I know that the expressions args -> queryXXXXSource(args) could be shortened to queryXXXXSource. But that would render the proposed solution harder to read because it's not obvious on first sight what is going to happen.
Yes, there is:
Arrays.asList(source1, source2, ...)
.stream()
.filter(s -> s != null)
.findFirst();
This is more flexible, since it returns an Optional not null in case a not-null source is found.
Edit: If you want lazy evaluation you should use a Supplier:
Arrays.<Supplier<Source>>asList(sourceFactory::getSource1, sourceFactory::getSource2, ...)
.stream()
.filter(s -> s.get() != null)
.findFirst();
It depends on some factors you are not defining. Do you have a fixed, rather small set of query…Source actions as shown in your question or are you rather heading to having a more flexible, extensible list of actions?
In the first case you might consider changing the query…Source methods to return an Optional<SomeObject> rather than SomeObject or null. If you change your methods to be like
Optional<SomeObject> queryFirstSource(Arguments args) {
…
}
You can chain them this way:
public SomeObject findSomeObject(Arguments args) {
return queryFirstSource(args).orElseGet(
()->querySecondSource(args).orElseGet(
()->queryThirdSource(args).orElse(null)));
}
If you can’t change them or prefer them to return null you can still use the Optional class:
public SomeObject findSomeObject(Arguments args) {
return Optional.ofNullable(queryFirstSource(args)).orElseGet(
()->Optional.ofNullable(querySecondSource(args)).orElseGet(
()->queryThirdSource(args)));
}
If you are looking for a more flexible way for a bigger number of possible queries, it is unavoidable to convert them to some kind of list or stream of Functions. One possible solution is:
public SomeObject findSomeObject(Arguments args) {
return Stream.<Function<Arguments,SomeObject>>of(
this::queryFirstSource, this::querySecondSource, this::queryThirdSource
).map(f->f.apply(args)).filter(Objects::nonNull).findFirst().orElse(null);
}
This performs the desired operation, however, it will compose the necessary action every time you invoke the method. If you want to invoke this method more often, you may consider composing an operation which you can re-use:
Function<Arguments, SomeObject> find = Stream.<Function<Arguments,SomeObject>>of(
this::queryFirstSource, this::querySecondSource, this::queryThirdSource
).reduce(a->null,(f,g)->a->Optional.ofNullable(f.apply(a)).orElseGet(()->g.apply(a)));
public SomeObject findSomeObject(Arguments args) {
return find.apply(args);
}
So you see, there are more than one way. And it depends on the actual task what direction to go. Sometimes, even the simple if sequence might be appropriate.
I would write it like this (you may not need generics here but why not do it):
public static <A, T> Optional<T> findFirst(Predicate<T> predicate, A argument,
Function<A, T>... functions) {
return Arrays.stream(functions)
.map(f -> f.apply(argument))
.filter(predicate::test)
.findFirst();
}
And you can call it with:
return findFirst(Objects::nonNull, args, this::queryFirstSource,
this::querySecondSource,
this::queryThirdSource);
(assuming your queryXXX methods are instance methods)
The methods will be applied in order until one returns a value that matches the predicate (in the example above: returns a non null value).