Saturday, April 25, 2015

Java 8- Optional

What is Optional in java 8?
Java 8 have added a class java.util.Optional to solve some of the problems associated with handling or manipulating the objects.
Its a container object which may or may not contain a non-null value.
Optional can hold a null or object. It allows to replace "!= null" or "== null" to more readable isPresent().It helps to map object to a different object or assign some defaults if original one is not present.

Why optional? Can't we achieve it with existing things?
Java started its journey by leaving behind the concept of pointer. In the course it got the curse of NullPointerException. Its not possible to find a java developer not fustrated with NPE. Optional provides one more wrapper over object. Proper use of Optional can free you from NPE.
Major part of java code is written to to check if object is null or not, then retrieve another object from it or manipulate its values. Optional makes these things easier and readable.

Enough, show me some code.
  • Optional can be created in three different ways.
  1. Optional<T> empty() : Provides optional object which doesn't has any value. It demostrates Null Object pattern
  2. Optional<T>of(T value): Should be used when you are sure that the object for which optional is created is not null. Example - Optional.of(new Student(23)); Throws NullPointerException if null is passed to the method.
  3. Optional<T> ofNullable: Should be used when you are not sure if value is null or not.
All 3 methods are static.

  • Getting rid of != null check
Optional<String> name = someMethodWhichGivesMeString();
if(name.isPresent()){
    System.out.println(name.get());
}
public Optional<String> someMethodWhichGivesMeString(){
return Optional.of("Sumit");
}
  • Making use of lambda expressions
Optional<String> name = someMethodWhichGivesMeString();
name.ifPresent(n -> System.out.println(n));

  • Mapping MangoDomain to MangoBean
Optional<Mango> mango = getMango();
// Inline mapping
Optional<MangoBean> mangoBean = mango.map(m -> new MangoBean(m.getColor()));
//Mapping extracted in separate method  
Optional<MangoBean> mangoBean2 = mango.map(Mango:: getMangoBean());

  • Mapping MangoDomain to MangoBean when mapper returns optional
map and flatMap are similar methods. The difference is the argument. flatMap method expects method which returns Optional.
Optional<Mango> mango = getMango();
MangoBean mangoBean = mango.flatMap(Mango:: getMangoBean());


  • Discard that rotten mango
Sometime, we have to filter object based on some logic.

  •  Optional<Mango> mango = mango.filter(m -> "GREEN".equals(m.getColor()) || "YELLOW".equals(m.getColor()));
If mango is green or yellow, then you will get it or it will be an empty optional object.


  •  Defaults...
While doing operations like map, filter etc, if the optional is empty then we can configure some default operations

  • mango.orElse(other)
It will return the value (mango) if present otherwise other of type Mango.
 mango.orElse(new Mango());


  • mango.orElseGet(supplier)
It will return the value (mango) if present otherwise return type Mango by invoking supplier.
mango.orElseGet(()->new Mango()); 


  • orElseThrow(Supplier<? extends X> exceptionSupplier)
It returns the mango value if present otherwise throws exception by invoking supplier.
mango.orElseThrow(()->new RuntimeException());    

Clubing everyting together

//Old way
        Mango mango = new Mango(YELLOW);
        Fruit fruit1;
        if(mango !=null &&
                YELLOW.equals(mango.getColor())){
            fruit1 = new Fruit(mango.getColor());
        }else{
            fruit1 = new Fruit(GREEN);
        }
   
//With Optional
        Optional<Mango> mangoOptional = Optional.of(new Mango(YELLOW));
        Fruit fruit = mangoOptional
                .filter(m -> YELLOW.equals(m.getColor()))//Filter Yellow mango
                .map(m -> new Fruit(m.getColor()))//Map it tp fruit
                .orElseGet(() -> new Fruit(GREEN));//if mango is not yellow or there is no mango at all create default fruit

Sources:
http://blog.jhades.org/java-8-how-to-use-optional/
http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html
https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html
http://www.concretepage.com/java/jdk-8/java-8-optional-example-avoid-nullpointerexception

No comments:

Post a Comment