What is Optional?

Java 8 has introduced a new class in utils package Optional. This class main purpose is for handling NullPointerExceptions.

So what exactly is Optional?

As per the oracle docs – Optional is a container object which may contain a value or may not contain a value.

In simple terms it means it can have values or it can be empty.

There are many in-build methods that optional has which helps us to avoid NullPointerException.

Example:


        String value1 = null;

        Optional<String> value2 = Optional.empty();

        if(value1!=null && value1.isEmpty()) { //Null check required
                System.out.println(value1) ;
        }

        Optional.ofNullable(value2).ifPresent(value -> System.out.println(value)); //Null check is done by optional

Method Explanation
empty()Returns an empty optional instance
filter(Predicate<? super T> predicate)If the value matches it returns optional value or returns optional empty
flatMap(Function<? super T, Optional<U>> mapper)Mapping function if value exists or optional empty
get()Gets the optional value if present or throws NoSuchElementException
ifPresent(Consumer<? super T> consumer)If optional value is present, proceed with consumer invocation or will not perform any operation
isPresent()Returns a boolean value, if value present returns true or false.
map(Function<? super T, ? extends U> mapper)Applies mapping function if the value is present
of(T value)Returns the optional value
ofNullable(T value)Returns a value if present or empty optional
orElse(T other)If value not present it returns the orElse value of other
orElseGet(Supplier<? extends T> other)Returns value if present or invokes other and returns the value
orElseThrow(Supplier<? extends X> exceptionSupplier)Returns value if present or throws the exception
Optional Methods

There also common methods in optional like toString() and hashcode().

How can we declare Optional and usage of Filter – here

What is a Map?

From oracle docs,


If a value is present, apply the provided mapping function to it, and if the result is non-null, return an Optional describing the result. Otherwise return an empty Optional.

A map will try to apply the function to the value and if the value is present it will return the value or it will return the empty optional.

Internal Implementation of Map:

    public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Optional.ofNullable(mapper.apply(value));
        }
    }

mapper is the mapping function to be applied over the value.

Exception Scenario:

Map will throw NullPointerException too, but on which situation?

Consider the below snippet,

Optional<String> noValue = null;

noValue.map(value -> value.toUpperCase(Locale.ROOT)); //throws NPE

The above code snippet will throw NullPointerException as we are trying to apply mapping function over a null value.

What happens if we try to apply Mapping function over Empty Optional?

Optional<String> emptyValue = Optional.empty();

System.out.println(emptyValue.map(val -> val.toLowerCase(Locale.ROOT))); //will this throw exception?

It will not throw exception. From the definition – if the result is non-null, return an Optional describing the result. Otherwise return an empty Optional .

The above code snippet will return empty optional.

Let us see the examples for Map,

        Optional<String> optValue = Optional.of("value1");

        Optional<String> emptyValue = Optional.empty();

        Optional<String> noValue = null;

        System.out.println(optValue.map(val -> val.toUpperCase(Locale.ROOT)));

        System.out.println(emptyValue.map(val -> val.toLowerCase(Locale.ROOT)));

        System.out.println(noValue.map(val -> val.toUpperCase(Locale.ROOT)));

Output:

Output of Map

What is Flatmap?

From oracle docs,

If a value is present, apply the provided Optional-bearing mapping function to it, return that result, otherwise return an empty Optional. This method is similar to map(Function), but the provided mapper is one whose result is already an Optional, and if invoked, flatMap does not wrap it with an additional Optional.

It is similar to map function but the difference is – Flatmap will not wrap with additional Optional.

Let us try to understand with an example,

class Engineer {

    private Optional<String> ename;

    public Engineer(Optional<String> ename) {
        this.ename = ename;
    }

    @Override
    public String toString() {
        return "Engineer{" +
                "ename=" + ename +
                '}';
    }

    public Optional<String> getEname() {
        return ename;
    }

    public void setEname(Optional<String> ename) {
        this.ename = ename;
    }
}

Map vs FlatMap:

        Optional<Engineer> engineer = Optional.of(new Engineer(Optional.of("Engineer1")));

        System.out.println(engineer.map(value -> value.getEname()));

        System.out.println(engineer.flatMap(value -> value.getEname()));

Output:

Map vs Flatmap

From the output, we can see the difference in Map vs FlatMap.

MapFlatMap
Map will apply the mapping function and if the result is not null – will return Optional describing the result Flatmap will apply the mapping function and if the result is not null and result already being an optional – flatmap does not wrap with additional Optional
From the above code – Optional[Optional[Engineer1]]From the above code – Optional[Engineer1]
Map vs Flatmap

From the output, flatmap did not wrap with additional optional and have provided the output.

Another example with List<Optional<Engineer>>,

        Optional<Engineer> engineer3 = Optional.of(new Engineer(Optional.of("Engineer3")));
        Optional<Engineer> engineer4 = Optional.of(new Engineer(Optional.of("Engineer4")));

        List<Optional<Engineer>> engList1 = Arrays.asList(engineer3, engineer4);

        System.out.println(engList1.stream().map(val -> val.map(Engineer::getEname)).collect(Collectors.toList()));

        System.out.println(engList1.stream().map(val -> val.flatMap(Engineer::getEname)).collect(Collectors.toList()));

Output:

From the output, In flatmap optional is not wrapped.

By Sri

Leave a Reply

Your email address will not be published. Required fields are marked *