Hello guys, I am back with a new blog, and this time, it is from our famous java version — Java 8.
In this blog, we will talk about how we can make good use of Optional class. Many of them find it difficult to understand that includes me as well. But, after going through various examples and trying it out on my own, I found it rather easy to use.
Before I plunge into the examples, let me first give you some background about Optional class.
You all must have written a hell lot of code in your life. But what is the most common exception you must have faced? The answer is The Deadly Null Pointer Exception. In most of the programs, null values needed to be handled first before you move on with your logic. Thus, creating a boilerplate code. To avoid such boilerplate code, Java 8 introduced a new type Optional<T> where T is the object type. Optional acts as a box that may or may not contain the actual object.
Let us understand some commonly used methods.
- Use Optional.of, when you are sure that you are dealing with a non-null value.
- Use Optional.ofNullable when you are unsure about the value ie the value may or may not be a null value.
- Use Optional.empty if you want to return an empty object.
- Use get method to get the actual object from the Optional.
Let us understand Optional with the help of an example.
Prior to Java 8, we used to write traditional for loops to iterate, and when a match is found we return the matched value (In the above program, it is the customer name) otherwise return null. The code looks a bit cluttered. Let us revisit the code by making use of Java streams and Optional class.
Do you see any change? Oh yes, we have optional into the picture. The findFirst method returns an Optional which contains the desired customer. But wait for a second, what if the box is empty? Huh, again an exception but this time a new villain — NoSuchElementException. How to solve this? Let us find out…
Yes, now we can safely commit the code to the production branch. What do you think? I feel it looks safe but hardly any better than a null check. Unfortunately, this just leads people into testing is present() before get()
Now its time to unveil few more members of Optional class
- .orElse(Default_data) — Returns value if present, or else a default value.
- .orElseGet(callSomeMethod) — Returns value if present, or else gets a default value by calling a supplier.
- orElseThrow(IllegalStateException::new) — Returns value if present, or else throws an exception obtained from a supplier.
- .map(Data::someMethod) — If present, transforms or map the value into another one and returns the result in Optional, otherwise returns an empty Optional.
These members look interesting!!! Let us use it.
The above code looks much cleaner and easy to understand. Thanks to the Optional class. But, we can further reduce the lines by getting rid of the Optional customer variable.
There are few more members in the Optional class which are very helpful.
- .filter(somePredicateObject) — If absent, return empty optional object. If present, applies the predicate to the value, and then it returns optional containing the value.
- ifPresent(someConsumerObject) — If present, executes a lambda (a consumer) on the value, otherwise does nothing.
In some cases, you can avoid if statements as well
Note: Avoid using Optional in fields, methods, and collections
Some important points to remember
- Optional is a box and it consumes 16 bytes.
- It is a separate object and potentially adds GC pressure.
- A single Optional is OK, but if you litter your data structure with many Optional instances, it could easily turn into a performance problem.
- Don’t replace every null with an Optional. Null can be safe if it is well controlled. Null in a private field can be easily checked.
That’s it from this blog. I hope you guys liked it.