Skip to main content

Java Optional

How to use Java Optional

In this article, we are going to see how we can use Java Optional which makes our code more readable, neat and clean And by using Optional, we can reduce the risk of unexpected occurrence of NullPointerException or avoid writing too many NullPointerException checks.

Content of the Article


What is Java Optional Class

Optional is a new class introduced in Java 8, An Optional Object can be considered as a container object which may contain a non-null or a null value. An optional containing null value called Empty Optional.

How to create objects using Java Optional

Now, start with the methods to create an object of Optional in Java 8. Mainly here are only 3 ways to create an instance of Optional class. Let's have a look at all of them one by one.

1. Using .of() method

The of() method is a static method of Optional class used to create an instance or object of Optional. This method takes an argument and returns an instance of Optional based on the object that we passed into the method as the argument. Let's understand this with an example.

Java Optional Example 1: Create Optional using of() method

Optional<String> optionalString = Optional.of("Java Optional");
Here, as we can see a string is passed as an argument to the method that's why it returns an optional of type string. Similarly, we can pass any type of object into this method and it will return an Optional of that type. But what happens if null or any object containing null passed as the argument, it will raise NullPointerException immediately. I will show later in this post how we can handle this.

2. Using .empty() method

The empty() method is also a static method, we can use this method to create an optional containing no value in it.

Java Optional Example 2: Create an empty Optional using empty() method

Optional<String> optionalString = Optional.empty();
In this case, I choose String as a type of Optional but We can choose any type here according to our needs.

3. Using .ofNullable() method

The ofNullable() method is same as of() method but if null or any object containing null passed as the argument into this method, it will not raise NullPointerException instead it will create an empty Optional to avoid any unexpected NullPointerException.

Java Optional Example 3: Create Optional using ofNullable() method

Optional<String> optionalString = Optional.ofNullable("Java Optional");

How to get value stored in Java Optional

Using .get() method

The Optional class provides a method named as get() which returns the value stored inside the Optional and then we can use the returned value according to our need.

Java Optional Example 4: Access the value of Optional using get() method

Optional<String> optionalString = Optional.ofNullable("Java Optional String");
String str = optionalString.get();
System.out.println(str);
Output
Java Optional String
But here is problem in using get() method, if the Optional is empty and still we invoke get() method then it will raise java.util.NoSuchElementException. To avoid this we should always use get() as:

Java Optional Example 5: Access the value of Optional using isPresent() and get() method

Optional<String> optionalString = Optional.ofNullable("Java Optional String");
if(optionalString.isPresent()) {
     String str = optionalString.get();
     System.out.println(str);
}
Output
Java Optional String
By using isPresent() method, it makes our code exception free. The isPresent() method is returns true if Optional is containing any non-null value otherwise false

Using .orElse() method

We can use orElse() method if we want to get a default value in case of empty Optional. When this method is invoked it returns the value containing by Optional(if non-null) otherwise default value. For example:

Java Optional Example 6: Access the value of Optional using orElse() method

Optional<String> optionalString = Optional.empty();
String str = optionalString.orElse("Any Default Value");
System.out.println(str);
Output
Any Default Value

Optional class also contains a method orElseGet() method which is similar to orElse(), but this method takes a Supplier which provide the default value instead providing default value direct. This method used where we need to calculate the default value.

How to use filter with Java Optional

The filter() method of Optional class is used to apply some kind of filter, this method takes a Predicate as an argument

A predicate is an interface of java.util package i.e., java.util.Predicate; and it is look like as:
Predicate<String> predicate = str -> str.contains("Java");

and apply that predicate onto the Optional If the value is present in the Optional, and the value matches the given predicate then return an Optional containing the value, otherwise returns an empty Optional. Let's understand this by an example

Java Optional Example 7: Filter the value of Optional

import java.util.Optional;

class Book {
    private String title;
    private String author;

    Book(String title, String author) {
       this.title = title;
       this.author = author;
    }

    public String getAuthor() {
       return author;
    }

    public String getTitle() {
       return title;
    }
}

class OptionalFilterExample {
    public static void main(String[] args) {
 
       Book book = new Book("Learn Java", "Shubham Bansal");
 
       // Filter the book containing Java in Title and Author is Shubham Bansal
       Optional<Book> optionalBook = Optional.ofNullable(book)
          .filter(b -> b.getTitle().contains("Java") && b.getAuthor().equals("Shubham Bansal"));
 
       if (optionalBook.isPresent()) {
           Book filteredBook = optionalBook.get();
           System.out.println(filteredBook.getTitle() + " By " + filteredBook.getAuthor());
       }
    }
}
Output
Learn Java By Shubham Bansal

How to change value of Java Optional

The Optional class provide map() method to perform any transformation onto the value of Optional. This method takes an argument of Function class

A Function is an interface of java.util package i.e., java.util.Function; and it is look like as:
Function<String> function = String::toUpperCase;

The map() method then apply that function onto the value within the Optional and return Optional containing transformed value.
Note : If function passed as the argument of map() transforms value to null then the empty Optional will be returned.

Let see how it works

Java Optional Example 8: Chnage the value of Optional using map() method

Book book = new Book("Learn Java", "Shubham Bansal");
Optional<Book> optionalBook = Optional.ofNullable(book);
Optional<String> optionalTitle = optionalBook.map(Book::getTitle);
if (optionalTitle.isPresent()) {
      String title = optionalTitle.get();
      System.out.println(title);
}
Output
Learn Java
As we can see Optional<Book> is now transformed into Optional<String> after using map() method.

Chaining of map() method

We can use a chain of map() methods to apply multiple transformations onto the value resides within the Optional. Also we can apply filter() intermediately for some kind of filtration task. For Example:

Java Optional Example 9: Chaining of map() method to change the value of Optional

Book book = new Book();
book.setTitle("Learn Java By Shubham Bansal");
 
Optional<String> optionalTitle = Optional.ofNullable(book)
  .map(Book::getTitle)
  .map(title -> title.toUpperCase())
  .filter(title -> title.contains("SHUBHAM"))
  .map(title -> title.concat(" 8TH EDITION"));
 
if (optionalTitle.isPresent()) {
     String title = optionalTitle.get();
     System.out.println(title);
}
Output
LEARN JAVA BY SHUBHAM BANSAL 8TH EDITION

There is also a variant of map() method exists known as flatMap(), this method also takes an argument of java.util.Function class but we use this method when the Function provided as the argument into flatMap() method transform the value into an another Optional or In other words to avoid the Situation of Optional<Optional<String>>.

How to avoid null checks using Java Optional

Before we are going to learn how to avoid too many null checks using Optional, first we should model a real world problem for better understanding.
Imagine we have a model where each Student is associated with a Course and each Course is associated with a Book. Lets first model this structure.
class Student {
    private String name;
    private Course course;

    public void setName(String name){
        this.name = name;
    }

    public void setCourse(Course course){
        this.course = course;
    }

    public String getName() {
        return name;
    }

    public Course getCourse() {
        return course;
    }
}

class Course {
    private String name;
    private Book book;

    public void setName(String name) {
        this.name = name;
    }

    public void setBook(Book book) {
        this.book = book;
    }

    public String getName() {
        return name;
    }

    public Book getBook() {
        return book;
    }
}

class Book {
    private String title;
    private String author;

    public void setTitle(String title) {
        this.title = title;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getAuthor() {
        return author;
    }

    public String getTitle() {
        return title;
    }
}
Now, we are going to use this model for further references.
Let suppose we need to write a method to get the name of the book that is associated with a Student via Course. Let see how it will look in Prior to Java 8.
String getBookTitle(Student student) {
     return student.getCourse().getBook().getTitle();
}
This code looks pretty good but here it is a issue, What happened getCourse() returns null or getBook() or student itself null. Then a NullPointerException will be raised and your code terminated unexpectedly. So one approach is we can use Null Check intermediately like:
String getBookTitle(Student student) {
       String defaultValue = "Title Not Found";

       if (student == null) {
           return defaultValue;
       }

       Course course = student.getCourse();
       if (course == null) {
           return defaultValue;
       }

       Book book = course.getBook();
       if (book == null) {
           return defaultValue;
       }

       String title = book.getTitle();
       if (title == null || title.equals("")) {
           return defaultValue;
       }

       return title;
}
The code is now exception free but it requires too much of checks and now it is not as pretty as before. We can achieve both its prettiness and simplicity through Java Optional. Let see how:
String getBookTitle(Student student) {
 
     String defaultValue = "Title Not Found";
     return Optional.ofNullable(student)
                 .map(st -> st.getCourse())
                 .map(course -> course.getBook())
                 .map(book -> book.getTitle())
                 .filter(title -> !title.equals(""))
                 .orElse(defaultValue);
}
Now, if any of Student, Course or Book is null then it will return the default value. Also, the code is simple, pretty, neat and clean.

How to remove If Block using Java Optional

Using .ifPresent() method

The ifPresent() method provides a way to remove If Block from our code. This method takes a argument of type Consumer class. If we invoked ifPresent() method onto an Optional and if it is not empty then the Consumer provided as the argument consumes the value within the Optional. Lets understand this with an example:

Java Optional Example 10: Remove if Block with the help of Optional

Book book = new Book();
book.setTitle("Learn Java By Shubham Bansal");

Optional<String> optionalTitle = Optional.ofNullable(book)
  .map(Book::getTitle)
  .map(title -> title.toUpperCase())
  .filter(title -> title.contains("SHUBHAM"))
  .map(title -> title.concat(" 8th Edition"));

// Without If block
System.out.println("-------------Output without using If Block---------------");
optionalTitle.ifPresent(title -> {
     System.out.println(title);
});
Output
-------------Output without using If Block---------------
LEARN JAVA BY SHUBHAM BANSAL 8TH EDITION

Related Article

Conclusion

So, that is all about Java Optional. By using this class efficiently we can make our code more error-free especially in case of Unexpected NullPointerException, also Optional makes our code easy to read, neat and clean.

Comments

Popular posts from this blog

How HashMap works internally in java

How Hashmap works Internally in Java In this article, we are going to see how HashMap internally works in java. Also, we will have a look at what Java 8 made changes on the internal working of Hashmap to make it faster. What is Hashmap and Hashing in java? How Hashmap works Internally in Java is majorly dependent upon the Hashing Principle. So, Before going to learn how HashMap works internally in java, lets first understand what is HashMap and hashing. HashMap : A HashMap is a map used to store mappings of key-value pairs. Also, it works on the Principle of Hashing. To know more about the HashMap, visit this article: HashMap in Java Hashing Principle : Simply, Hashing is a method used to produce an integer value from an object and this integer value known as the hash value. In HashMap, the key object is used for Hashing.
Internal Struture of the HashMap in java For internal working of HashMap, HashMap maintains an array of bucket, each bucket is a linked-list and linked list is a li…

HashMap in Java

HashMap in Java In this article, we are going to learn about the most important class of Java known as HashMap. HashMap in java is the most used map interface and it is used in our regular or day-to-day programming practices.
What is HashMap in java? Lets first start with basic definition of HashMap,
HashMap is a map which store key-value pair, where each key is mapped with a value.
HashMap defined in java.util package and implements map interface which provides functionalities to perform basic operation like store, retrieve, size of the map etc. It is a part of Java Collection Framework. Time complexity of HashMap in Java? : Time complexity to store and retrieve data from the HashMap is O(1) in the Best Case. But it can be O(n) in the worst case and after the changes made in Java 8 the worst case time complexity can be O(log n) atmost. Internal working of HashMap in java HashMap maintains an array of the buckets, where each bucket is a linked-list and the linked list is a list of…

ArrayList in Java

ArrayList in Java In this article, we are going to discuss ArrayList in Java. ArrayList is a class from the Java Collection Framework and widely in our programs. We use ArrayList as a substitute for the array. So, it is important to know ArrayList in detail. We are going to see what is ArrayList in Java, how we can create the instance of ArrayList and the methods provided by the ArrayList in Java.

If you already familiar to ArrayList, you may learn common programs related to ArrayList.
Table of ContentsWhat is ArrayList in Java?Hierarchy of the ArrayList in java?How to create objects of ArrayList in Java?How to create an ArrayList of Custom Objects?How to iterate ArrayList in Java?How to get the elements by index from ArrayList in Java?How to check whether an elements is stored in the ArrayList in Java?How to remove elements from the ArrayList in Java?Few more methods of ArrayList in Java?
What is ArrayList in Java? ArrayList in Java is a List in which we can store and retrieve elemen…