I am trying to understand the ifPresent() method of the Optional API in Java 8.

I have simple logic:

Optional<User> user=... user.ifPresent(doSomethingWithUser(user.get())); 

But this results in a compilation error:

ifPresent(java.util.functionError:(186, 74) java: 'void' type not allowed here) 

Of course I can do something like this:

if(user.isPresent()) { doSomethingWithUser(user.get()); } 

But this is exactly like a cluttered null check.

If I change the code into this:

 user.ifPresent(new Consumer<User>() { @Override public void accept(User user) { doSomethingWithUser(user.get()); } }); 

The code is getting dirtier, which makes me think of going back to the old null check.

Any ideas?

5 Answers

Optional<User>.ifPresent() takes a Consumer<? super User> as argument. You're passing it an expression whose type is void. So that doesn't compile.

A Consumer is intended to be implemented as a lambda expression:

Optional<User> user = ... user.ifPresent(theUser -> doSomethingWithUser(theUser)); 

Or even simpler, using a method reference:

Optional<User> user = ... user.ifPresent(this::doSomethingWithUser); 

This is basically the same thing as

Optional<User> user = ... user.ifPresent(new Consumer<User>() { @Override public void accept(User theUser) { doSomethingWithUser(theUser); } }); 

The idea is that the doSomethingWithUser() method call will only be executed if the user is present. Your code executes the method call directly, and tries to pass its void result to ifPresent().

8

In addition to @JBNizet's answer, my general use case for ifPresent is to combine .isPresent() and .get():

Old way:

Optional opt = getIntOptional(); if(opt.isPresent()) { Integer value = opt.get(); // do something with value } 

New way:

Optional opt = getIntOptional(); opt.ifPresent(value -> { // do something with value }) 

This, to me, is more intuitive.

3

Why write complicated code when you could make it simple?

Indeed, if you are absolutely going to use the Optional class, the most simple code is what you have already written ...

if (user.isPresent()) { doSomethingWithUser(user.get()); } 

This code has the advantages of being

  1. readable
  2. easy to debug (breakpoint)
  3. not tricky

Just because Oracle has added the Optional class in Java 8 doesn't mean that this class must be used in all situation.

3

You can use method reference like this:

user.ifPresent(ClassNameWhereMethodIs::doSomethingWithUser); 

Method ifPresent() get Consumer object as a paremeter and (from JavaDoc): "If a value is present, invoke the specified consumer with the value." Value it is your variable user.

Or if this method doSomethingWithUser is in the User class and it is not static, you can use method reference like this:

user.ifPresent(this::doSomethingWithUser); 
4

Use flatMap. If a value is present, flatMap returns a sequential Stream containing only that value, otherwise returns an empty Stream. So there is no need to use ifPresent() . Example:

list.stream().map(data -> data.getSomeValue).map(this::getOptinalValue).flatMap(Optional::stream).collect(Collectors.toList()); 
2

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy