Java 8 Optional Examples

0

Java 8 introduces a new class called java.util.Optional<T> that represents encapsulation of an optional value.

Instead of returning the value directly, a wrapper object is returned so that we don’t get into the trap of NullpointerException.

We can verify whether the object exists by calling Optional.isPresent(). The actual object can be retrieved using Optional.get() but before calling it, we need to make sure that the object exists else it will throw a NoSuchElementException.

Since the absence or presence of an object is modeled now using Option, there is less chance for programmer to forget checking for the presence of object.

Creation of Optional objects

How do you create Optional objects?

  1. Using Optional.of(Object) to hold not-null value
  2. Using Optional.empty() to create empty Optional
  3. If you already have a value but are not sure whether it is null or not-null then call Optional.ofNullable(object)

In this example, there is a Seed object which grows into Fruit. Each Fruit has a price. The price is optional, in the sense, if it is not set, default would be 100.

Seed:

package com.javarticles.java8.stream;

import java.util.Optional;

public class Seed {
    private String name;

    public Seed(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
    
    public Optional<Fruit> growIntoFruit() {
        return Optional.of(new Fruit(this));
    }
    
    public Optional<Fruit> growIntoFruit(Integer price) {
        return Optional.of(new Fruit(this, price));
    }
}

Fruit:

package com.javarticles.java8.stream;

import java.util.Optional;

public class Fruit {
    private Seed seed;
    private Optional<Integer> optionalPrice;
    
    public Fruit(Seed seed) {
        this.seed = seed;
        this.optionalPrice = Optional.empty();
    }
    
    public Fruit(String name, Integer price) {
        this.seed = new Seed(name);
        this.optionalPrice = Optional.of(price);
    }
    
    public Fruit(Seed seed, Integer price) {
        this.seed = seed;
        this.optionalPrice = Optional.of(price);
    }

    public Optional<Integer> getPrice() {
        return optionalPrice;
    }

    public void eat() {
        System.out.println("Found " + seed.getName() + ", let's eat...");
    }

    public Seed getSeed() {
        return seed;
    }

    public void setPrice(int price) {
        optionalPrice = Optional.of(price);        
    }       
}

We create an empty seed and check using isPresent() whether the Optional<Seed> created is empty.

Take a look at the below statement. The Optional mango seed created is grown into fruit, then we fetch its price. If it is null, a default value of 100 is returned.

mangoSeed.flatMap(Seed::growIntoFruit).flatMap(Fruit::getPrice).orElse(100);

orElse() method provides a default value if Optional is empty.

In the next statement, we explicitly set a price to the grown fruit.

mangoSeed.flatMap(seed -> seed.growIntoFruit(200)).flatMap(Fruit::getPrice).orElse(100);

Let’s see the complete example.

OptionalCreationExample:

package com.javarticles.java8.stream;

import java.util.Optional;

public class OptionalCreationExample {

    public static void main(String[] args) {
        Optional<Seed> emptySeed = Optional.empty();
        System.out.println("Is Seed empty? " + !emptySeed.isPresent());
        
        Optional<Seed> mangoSeed = Optional.of(new Seed("Mango Seed"));
        System.out.println("Does mango seed exists? " + mangoSeed.isPresent());
        
        Integer price = mangoSeed.flatMap(Seed::growIntoFruit).flatMap(Fruit::getPrice).orElse(100);        
        System.out.println("Price of mango is " + price);
        
        price = mangoSeed.flatMap(seed -> seed.growIntoFruit(200)).flatMap(Fruit::getPrice).orElse(100);        
        System.out.println("Price of mango is " + price);
    }
}

Output:

Is Seed empty? true
Does mango seed exists? true
Price of mango is 100
Price of mango is 200

Example of Optional Object using Filter

In this example, we will use filter to select only those fruits whose price is less than 20.

Optional optional = Arrays.stream(fruits).filter(f -> f.getPrice().get() < 20).findAny();

We use findAny() to find fruits for the price we are interested in. It may or may not find any fruits so it returns an Optional Object. Since there is no fruit for price 20, the isPresent will return false.

If we call get() method to get the wrapped fruit, it will throw a NoSuchElementException exception.

try {
         optional.get();
    } catch(java.util.NoSuchElementException e) {
         System.out.println("If there is no fruit found, optional.get() throws NoSuchElementException");
    }

Next, we try to find fruits for price less than 200. We find many, of which we will get the first one. If  the fruit is present, we eat it.

Arrays.stream(fruits).filter(f -> f.getPrice().get() < 200).findFirst().ifPresent(f -> f.eat());

ifPresent(Consumer block) executes the given block if a value is present.

OptionalExample:

package com.javarticles.java8.stream;

import java.util.Arrays;
import java.util.Optional;

public class OptionalExample {

    public static void main(String[] args) {
        Fruit[] fruits = {new Fruit("Mangoe", 80), new Fruit("Apple", 100), new Fruit("Orange", 80)};
        System.out.println("Find fruits  for a price less than 20, shouldn't be able to find any");
        Optional<Fruit> optional = Arrays.stream(fruits).filter(f -> f.getPrice().get() < 20).findAny();
        System.out.println("Got any? " + optional.isPresent());
        try {
            optional.get();
        } catch(java.util.NoSuchElementException e) {
            System.out.println("If there is no fruit found, optional.get() throws NoSuchElementException");
        }
        System.out.println("Find fruits  for a price less than 200");
        Arrays.stream(fruits).filter(f -> f.getPrice().get() < 200)
        .findFirst()
        .ifPresent(f -> f.eat());
    }
}

Output:

Find fruits  for a price less than 20, shouldn't be able to find any
Got any? false
If there is no fruit found, optional.get() throws NoSuchElementException
Find fruits  for a price less than 200
Found Mangoe, let's eat...

Download the source code

This was an example about Java 8 Optional class. You can download the source code here: optionalExamples.zip

Share.

Comments are closed.