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.
Advertisement
Answer
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:
- can define the functionality before the existing of an object easy.
- not creating object reference for each Optional, only one, you have so less memory than less GC.
- it is implementing consumer for better usage with other components.
By the way, now its name is more descriptive it is actually Consumer<Optional<?>>