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.
For me the answer of @Dane White is OK, first I did not like using Runnable
but I could not find any alternatives.
Here another implementation I preferred more:
public class OptionalConsumer<T> {
private Optional<T> optional;
private OptionalConsumer(Optional<T> optional) {
this.optional = optional;
}
public static <T> OptionalConsumer<T> of(Optional<T> optional) {
return new OptionalConsumer<>(optional);
}
public OptionalConsumer<T> ifPresent(Consumer<T> c) {
optional.ifPresent(c);
return this;
}
public OptionalConsumer<T> ifNotPresent(Runnable r) {
if (!optional.isPresent()) {
r.run();
}
return this;
}
}
Then:
Optional<Any> o = Optional.of(...);
OptionalConsumer.of(o).ifPresent(s -> System.out.println("isPresent " + s))
.ifNotPresent(() -> System.out.println("! isPresent"));
Update 1:
the above solution for the traditional way of development when you have the value and want to process it but what if I want to define the functionality and the execution will be then, check below enhancement;
public class OptionalConsumer<T> implements Consumer<Optional<T>> {
private final Consumer<T> c;
private final Runnable r;
public OptionalConsumer(Consumer<T> c, Runnable r) {
super();
this.c = c;
this.r = r;
}
public static <T> OptionalConsumer<T> of(Consumer<T> c, Runnable r) {
return new OptionalConsumer(c, r);
}
@Override
public void accept(Optional<T> t) {
if (t.isPresent()) {
c.accept(t.get());
}
else {
r.run();
}
}
Then could be used as:
Consumer<Optional<Integer>> c = OptionalConsumer.of(
System.out::println,
() -> System.out.println("Not fit")
);
IntStream.range(0, 100)
.boxed()
.map(i -> Optional.of(i)
.filter(j -> j % 2 == 0))
.forEach(c);
In this new code you have 3 things:
By the way, now its name is more descriptive it is actually Consumer<Optional<?>>