In Java 8, I want to do something to an Optional
object if it is present, and do another thing if it is not present.
if (opt.isPresent()) {
System.out.println("found");
} else {
System.out.println("Not found");
}
This is not a 'functional style', though.
Optional
has an ifPresent()
method, but I am unable to chain an orElse()
method.
Thus, I cannot write:
opt.ifPresent( x -> System.out.println("found " + x))
.orElse( System.out.println("NOT FOUND"));
In reply to @assylias, I don't think Optional.map()
works for the following case:
opt.map( o -> {
System.out.println("while opt is present...");
o.setProperty(xxx);
dao.update(o);
return null;
}).orElseGet( () -> {
System.out.println("create new obj");
dao.save(new obj);
return null;
});
In this case, when opt
is present, I update its property and save to the database. When it is not available, I create a new obj
and save to the database.
Note in the two lambdas I have to return null
.
But when opt
is present, both lambdas will be executed. obj
will be updated, and a new object will be saved to the database . This is because of the return null
in the first lambda. And orElseGet()
will continue to execute.
This question is related to
java
functional-programming
java-8
optional
If you are using Java 9+, you can use ifPresentOrElse()
method:
opt.ifPresentOrElse(
value -> System.out.println("Found: " + value),
() -> System.out.println("Not found")
);
You cannot call orElse
after ifPresent
, the reason is, orElse
is called on an optiional but ifPresent
returns void. So the best approach to achieve is ifPresentOrElse
.
It could be like this:
op.ifPresentOrElse(
(value)
-> { System.out.println(
"Value is present, its: "
+ value); },
()
-> { System.out.println(
"Value is empty"); });
Supposing that you have a list and avoiding the isPresent()
issue (related with optionals) you could use .iterator().hasNext()
to check if not present.
In case you want store the value:
Pair.of<List<>, List<>> output = opt.map(details -> Pair.of(details.a, details.b))).orElseGet(() -> Pair.of(Collections.emptyList(), Collections.emptyList()));
There isn't a great way to do it out of the box. If you want to be using your cleaner syntax on a regular basis, then you can create a utility class to help out:
public class OptionalEx {
private boolean isPresent;
private OptionalEx(boolean isPresent) {
this.isPresent = isPresent;
}
public void orElse(Runnable runner) {
if (!isPresent) {
runner.run();
}
}
public static <T> OptionalEx ifPresent(Optional<T> opt, Consumer<? super T> consumer) {
if (opt.isPresent()) {
consumer.accept(opt.get());
return new OptionalEx(true);
}
return new OptionalEx(false);
}
}
Then you can use a static import elsewhere to get syntax that is close to what you're after:
import static com.example.OptionalEx.ifPresent;
ifPresent(opt, x -> System.out.println("found " + x))
.orElse(() -> System.out.println("NOT FOUND"));
Another solution could be following:
This is how you use it:
final Opt<String> opt = Opt.of("I'm a cool text");
opt.ifPresent()
.apply(s -> System.out.printf("Text is: %s\n", s))
.elseApply(() -> System.out.println("no text available"));
Or in case you in case of the opposite use case is true:
final Opt<String> opt = Opt.of("This is the text");
opt.ifNotPresent()
.apply(() -> System.out.println("Not present"))
.elseApply(t -> /*do something here*/);
This are the ingredients:
The "cosmetically" enhanced Function interface.
@FunctionalInterface
public interface Fkt<T, R> extends Function<T, R> {
default R elseApply(final T t) {
return this.apply(t);
}
}
And the Optional wrapper class for enhancement:
public class Opt<T> {
private final Optional<T> optional;
private Opt(final Optional<T> theOptional) {
this.optional = theOptional;
}
public static <T> Opt<T> of(final T value) {
return new Opt<>(Optional.of(value));
}
public static <T> Opt<T> of(final Optional<T> optional) {
return new Opt<>(optional);
}
public static <T> Opt<T> ofNullable(final T value) {
return new Opt<>(Optional.ofNullable(value));
}
public static <T> Opt<T> empty() {
return new Opt<>(Optional.empty());
}
private final BiFunction<Consumer<T>, Runnable, Void> ifPresent = (present, notPresent) -> {
if (this.optional.isPresent()) {
present.accept(this.optional.get());
} else {
notPresent.run();
}
return null;
};
private final BiFunction<Runnable, Consumer<T>, Void> ifNotPresent = (notPresent, present) -> {
if (!this.optional.isPresent()) {
notPresent.run();
} else {
present.accept(this.optional.get());
}
return null;
};
public Fkt<Consumer<T>, Fkt<Runnable, Void>> ifPresent() {
return Opt.curry(this.ifPresent);
}
public Fkt<Runnable, Fkt<Consumer<T>, Void>> ifNotPresent() {
return Opt.curry(this.ifNotPresent);
}
private static <X, Y, Z> Fkt<X, Fkt<Y, Z>> curry(final BiFunction<X, Y, Z> function) {
return (final X x) -> (final Y y) -> function.apply(x, y);
}
}
This should do the trick and could serve as a basic template how to deal with such requirements.
The basic idea here is following. In a non functional style programming world you would probably implement a method taking two parameter where the first is a kind of runnable code which should be executed in case the value is available and the other parameter is the runnable code which should be run in case the value is not available. For the sake of better readability, you can use curring to split the function of two parameter in two functions of one parameter each. This is what I basically did here.
Hint: Opt also provides the other use case where you want to execute a piece of code just in case the value is not available. This could be done also via Optional.filter.stuff but I found this much more readable.
Hope that helps!
Good programming :-)
The described behavior can be achieved by using Vavr (formerly known as Javaslang), an object-functional library for Java 8+, that implements most of Scala constructs (being Scala a more expressive language with a way richer type system built on JVM). It is a very good library to add to your Java projects to write pure functional code.
Vavr provides the Option
monad that provides functions to work with the Option type such as:
fold
: to map the value of the option on both cases (defined/empty)onEmpty
: allows to execute a Runnable
when option is emptypeek
: allows to consume the value of the option (when defined).Serializable
on the contrary of Optional
which means you can safely use it as method argument and instance member.Option follows the monad laws at difference to the Java's Optional "pseudo-monad" and provides a richer API. And of course you can make it from a Java's Optional (and the other way around): Option.ofOptional(javaOptional)
–Vavr is focused on interoperability.
// AWESOME Vavr functional collections (immutable for the gread good :)
// fully convertible to Java's counterparts.
final Map<String, String> map = Map("key1", "value1", "key2", "value2");
final Option<String> opt = map.get("nonExistentKey"); // you're safe of null refs!
final String result = opt.fold(
() -> "Not found!!!", // Option is None
val -> "Found the value: " + val // Option is Some(val)
);
Moreover, all Vavr types are convertible to its Java counterparts, for the sake of the example: Optional javaOptional = opt.toJava()
, very easy :) Of course the conversion also exists in the other way: Option option = Option.ofOptional(javaOptional)
.
N.B. Vavr offers a io.vavr.API
class with a lot of convenient static methods =)
Null reference, the billion dollar mistake
N.B. This is only a very little example of what Vavr offers (pattern matching, streams a.k.a. lazy evaluated lists, monadic types, immutable collections,...).
Java 9 introduces
See excellent Optional in Java 8 cheat sheet.
It provides all answers for most use cases.
Short summary below
opt.ifPresent(x -> print(x));
opt.ifPresent(this::print);
opt.filter(x -> x.contains("ab")).ifPresent(this::print);
opt.map(String::trim).filter(t -> t.length() > 1).ifPresent(this::print);
int len = opt.map(String::length).orElse(-1);
int len = opt.
map(String::length).
orElseGet(() -> slowDefault()); //orElseGet(this::slowDefault)
opt.
filter(s -> !s.isEmpty()).
map(s -> s.charAt(0)).
orElseThrow(IllegalArgumentException::new);
Another solution would be to use higher-order functions as follows
opt.<Runnable>map(value -> () -> System.out.println("Found " + value))
.orElse(() -> System.out.println("Not Found"))
.run();
An alternative is:
System.out.println(opt.map(o -> "Found")
.orElse("Not found"));
I don't think it improves readability though.
Or as Marko suggested, use a ternary operator:
System.out.println(opt.isPresent() ? "Found" : "Not found");
If you can use only Java 8 or lower:
1) if you don't have spring-data
the best way so far is:
opt.<Runnable>map(param -> () -> System.out.println(param))
.orElse(() -> System.out.println("no-param-specified"))
.run();
Now I know it's not so readable and even hard to understand for someone, but looks fine for me personally and I don't see another nice fluent way for this case.
2) if you're lucky enough and you can use spring-data
the best way is
Optionals#ifPresentOrElse:
Optionals.ifPresentOrElse(opt, System.out::println,
() -> System.out.println("no-param-specified"));
If you can use Java 9, you should definitely go with:
opt.ifPresentOrElse(System.out::println,
() -> System.out.println("no-param-specified"));
Source: Stackoverflow.com