Monday

Optional in java 8 & 9

I'll try to give example for Optional class which has came up for NullPointerException. It is a wrapper class, it can contain any other Object or it can be empty. Java 8 features:

Create Optional instances:
//You can create an empty Optional instance.
Optional.empty();
 
//of() method will throw NullPointerException if the user is null
//you should use of() method only if you are sure that your object is not null
Optional<User> opt = Optional.of(user);

//ofNullable() method can be use if the user object is null or not null.
Optional<User> opt = Optional.ofNullable(user);

Retrieve the actual object inside Optional instance:
//you can use get() method but if the user object is null then it will throw NoSuchElementException.
Optional<User> opt = Optional.ofNullable(user);
User myUser = opt.get();

//so, you should first check the value is present or not
//isPresent() method can be use
Optional<User> opt = Optional.ofNullable(user);
if(opt.isPresent()) {
 User myUser = opt.get();
 //your other jobs
}

//There is also ifPresent() method which combines isPresent() and get()
//lambda expression is used
Optional<User> opt = Optional.ofNullable(user);
opt.ifPresent(myUser -> {
    ///your other jobs
})

Return values:
//orElse() method returns the values if it's present, if not present then returns the other argument
//if user is not null then returns it. Otherwise returns user2.
User myUser = Optional.ofNullable(user).orElse(user2);


//orElseGet() method returns the values if it's present,
//if not present then executes Supplier interface
User myUser = Optional.ofNullable(user).orElseGet( () -> user2);

Lets see the difference between orElse() and orElseGet().
In the following example object is null and both return the other object. There is no difference as you see but....
User user = null; 
System.out.log("orElse>> ");
User myUser = Optional.ofNullable(user).orElse(createUser());
System.out.log(myUser.getName());
System.out.log("orElseGet>> ");
User myUser = Optional.ofNullable(user).orElseGet( () -> createUser());
System.out.log(myUser.getName());

...
private User createUser() {
    logger.debug("createUser method inside");
    return new User("eda2");
}

/*
 Output:
  orElse>>
  createUser method inside
  eda2
  orElseGet>>
  createUser method inside
  eda2
*/

In the following example object is not null.
But even if object is not null orElse() method has gone createUser() method.
orElse() always will call the given function() but orElseGet() will call only if optional is not present.
So orElse() is very expensive for the resources!!!!!!
User user = new User("eda"); 
System.out.log("orElse>> ");
User myUser = Optional.ofNullable(user).orElse(createUser());
System.out.log(myUser.getName());
System.out.log("orElseGet>> ");
User myUser = Optional.ofNullable(user).orElseGet( () -> createUser());
System.out.log(myUser.getName());

...
private User createUser() {
    logger.debug("createUser method inside");
    return new User("eda2");
}

/*
 Output:
  orElse>>
  createUser method inside
  eda
  orElseGet>>
  eda
*/

Return exception:
//orElseThrow() throws an exception if the object is empty:
User myUser = Optional.ofNullable(user).orElseThrow(() -> new UserDoesNotExist());

Mapping:
//map() method applies the functional argument to the value and returns the result.
User user = new User("eda"); 
String userName = Optional.ofNullable(user)
 .map(myUser -> myUser.getName()).orElse("DEFAULT NAME");

//if the get method returns an Optional value you can use flatMap() and return unwrapped String value.
public class User {    
    private String name;

    public Optional<String> getName() {
        return Optional.ofNullable(name);
    }

}

User user = new User("eda");
String userName = Optional.ofNullable(user)
 .flatMap(myUser -> myUser.getName()).orElse("DEFAULT NAME");

Filtering:
//filter() method
//optUser will not contain a null name value.
User user = new User(null);
Optional<User> optUser = Optional.ofNullable(user)
  .filter(myUser -> myUser.getName() != null);

//optUser.isPresent() is false, in this case filter returns empty Optional.

Features that come with Java 9 to Optional class:
Java 9 added 3 more methods to the Optional class:  or(), ifPresentOrElse() and stream().
or() method:
//orElse() and orElseGet() methods returns unwrapped values.
//or() method is similar with them but it returns Optional object.
User user = "eda"; 
Optional<User> myUser = Optional.ofNullable(user).or(() -> createUser());
//User myUser = Optional.ofNullable(user).or(() -> createUser()).get();
System.out.log(myUser.get().getName());
System.out.log("**");
...

User user = null; 
Optional<User> myUser = Optional.ofNullable(user).or(() -> createUser());
System.out.log(myUser.get().getName());
...

private Optional<User>  createUser() {
    logger.debug("createUser method inside");
    return Optional.of(new User("eda2"));
}

/*
 Output:
  eda
  **
  createUser method inside
  eda2
*/

ifPresentOrElse() method:
It gives us a change to run a function if the optional is empty.
Optional<User> opt = Optional.ofNullable(user);
opt.ifPresentOrElse(myUser -> 
    ///your other jobs, myUser.getName()
 , () -> logger.info("User not found")
);

stream() method:
I'll mention about stream in an another writing.
User user = new User("eda");
List<String> nameList = Optional.ofNullable(user)
   .stream()
   .filter(u -> u.getName() != null)
   .map(u -> u.getName())
   .collect(Collectors.toList());

No comments:

Post a Comment