DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
  1. DZone
  2. Coding
  3. Java
  4. Oogways: Advice on Optional in Java 8

Oogways: Advice on Optional in Java 8

Want to learn more about using Optionals in Java? Check out this post to learn more about why passing an Optional in the input is a bad idea!

Shamik Mitra user avatar by
Shamik Mitra
·
Aug. 29, 18 · Presentation
Like (18)
Save
Tweet
Share
11.97K Views

Join the DZone community and get the full member experience.

Join For Free

Oogway's previous talk clears all the confusions on why Optional is added to Java 8. But, PO is a dragon warrior, and he is the finest Java warrior around. He wants to know more; he wants to know it is time to use Optional. What are the best practices? So, PO went to Oogways to have a talk about Optionals.

Here is their conversation:

PO: Master Oogway, I completely understand why we use Optional — it gives the caller a hint that the output may not be available, so design your code accordingly. It is a conceptual improvement that forces the caller to tackle a scenario and the output is a less null pointer exception. But, how do we use it efficiently?

Oogways: PO, listen carefully: Optional is created to check whether a return value from a method is present or not. So, it is the only time you should use Optional and nothing else. Optional acts as a container and wraps the return value, applying different functions on it to determine if its value is present or not. In advance, if the value is present, it can take necessary functions on it in a functional way. But, the case of Optional must be used with the method return type. Using Optional<T> as a composition or passing it as an input is a very lame idea and should be avoided.

PO: What is the problem with passing Optional as an input? Suppose I have a program to search a name, so if I pass the name as Optional<String>, the developer doesn't have to perform the null check.

For more information, see the below program:

package com.example.optional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class OptionalTest {

private static List<String>nameList = new ArrayList<String>();

static {
nameList.add("shamik");
nameList.add("samir");
nameList.add("swastika");
}

Optional<String> findName(Optional<String> name){
return name.isPresent()?Optional.of(nameList.get(nameList.indexOf(name.get().toLowerCase()))):Optional.empty();
}

public static void main(String[] args) {
OptionalTest optionalTest = new OptionalTest();
Optional<String> searchedNameOptional = optionalTest.findName(Optional.of("Shamik"));
Optional<String> searchedNameOptionalSecond  = optionalTest.findName(Optional.ofNullable(null));
searchedNameOptional.ifPresent(System.out::println);
searchedNameOptionalSecond.ifPresent(System.out::println);
}

}


Here, I create a method called  findName, which takes an Optional<String>. So, the developer can check if the value is present it returns an Optional<String> or an empty Optional. There is no null check involved, and passing the Optional caller signal to the developer that is passing the parameter may be present or absent, so deal with this accordingly. I think this is a nice way to tackle input parameters. So, master, why are you are telling me that passing an Optional in the input is a bad idea?

Oogway: PO, there is a subtle conceptual error in your thinking.

You are right — Optional is used for signaling whether a value can be present or absent. But, think about who is signaling to whom. Here, the caller is signaling to the author of the code. The author is the creator of the code, and the author is very sure about what it's method input does and returns for each method. Here, signaling is meaningless. If you only pass the name, in this case, the author, it also knows that the value may be null as the default value of String is null. But, the author can take care of it, With using Optional, it becomes a bit redundant. Optional means that the developer of the code reminds themselves that passing the parameter may be present or absent, but this is just nonsense. Optional works fine for the client of the method as the client does not know what the method is doing inside. The author only knows this information by the call findName. I can get an Optional<String >. This method may give a blank result, so I need to tackle it. But, the reverse perspective is false. There is no need to signal to the developer, who controls the implementation, what they need to do with inputs. In this case, the null check is better than Optional. Another thing is when passing Optional, you create a wrapper on a value that takes more memory space of an unnecessary, complex code.  Also, the caller has to create an Optional container, which is a break of encapsulation. The best way to represent your code is the following:

package com.example.optional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class OptionalTest {

private static List<String>nameList = new ArrayList<String>();

static {
nameList.add("shamik");
nameList.add("samir");
nameList.add("swastika");
}

Optional<String> findName(String name){
return name !=null?Optional.of(nameList.get(nameList.indexOf(name.toLowerCase()))):Optional.empty();
}


public static void main(String[] args) {
OptionalTest optionalTest = new OptionalTest();
Optional<String> searchedNameOptional = optionalTest.findName("Shamik");
Optional<String> searchedNameOptionalSecond  = optionalTest.findName(null);
searchedNameOptional.ifPresent(System.out::println);
searchedNameOptionalSecond.ifPresent(System.out::println);
}

}


In this way, the developer issued the null check. However, always remember that Optional is not an option for replacing the null or applying some fancy methods on a value like  filter/map , etc. The Optional is for signaling if a value is present or not. So, don't use it in composition or input variables just for the sake of using Optional.

PO: Now, I understand, master! Please, tell me, what are some of the operations we can perform using Optional?

Oogways: Yes, PO, now we are in a position where we can use some of Optional 's utility methods.

Sometimes, if a value is not present, in that case, you can use orElse on the Optional. Suppose, if the name is not found, we show "NA" as the default value. In that case, we can change the findName  method to the following:

package com.example.optional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class OptionalTest {

private static List<String>nameList = new ArrayList<String>();

static {
nameList.add("shamik");
nameList.add("samir");
nameList.add("swastika");
}



public String findName(String name){
return Optional.ofNullable(name).map(val->nameList.get(nameList.indexOf(val.toLowerCase()))).orElse("NA");

}





public static void main(String[] args) {
OptionalTest optionalTest = new OptionalTest();
String blankName = optionalTest.findName(null);
String name = optionalTest.findName("Shamik");
System.out.println("Name is :: " + blankName);
System.out.println("Name is :: " + name);

}

}


Here, I use a map function that will check to see if the name is in name List or not. If it is not found, it will return "NA," as in  orElse, and I provide a default value as "NA."

Now, if the default value is fetched from the database or a Properties file, then we need to write a separate method, which returns the default value. In that case, we can use that separate method as a reference and pass a supplier interface in the orElseGet method. Check out the following example:

package com.example.optional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class OptionalTest {

private static List<String>nameList = new ArrayList<String>();

static {
nameList.add("shamik");
nameList.add("samir");
nameList.add("swastika");
}

String findNameWithSupplier(String name){
return Optional.ofNullable(name).map(val->nameList.get(nameList.indexOf(val.toLowerCase()))).orElseGet(()->"NA");

}

public static void main(String[] args) {
OptionalTest optionalTest = new OptionalTest();
String blankName = optionalTest.findNameWithSupplier(null);
String name = optionalTest.findNameWithSupplier("Shamik");
System.out.println("Name is :: " + blankName);
System.out.println("Name is :: " + name);

}

}


Optional has two utility functions called isPresent and ifPresent. The former returns true if a value present later takes a callback function, which will apply to the value when the value is present. So, when you see a code block like the following:

if(optional.isPresent()){
  doSomething();
}


Then, you will need to replace the same with ifPresent:

optional.ifPresent(val->doSomething())


For more, see the additional example below:

package com.example.optional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class OptionalTest {

private static List<String>nameList = new ArrayList<String>();

static {
nameList.add("shamik");
nameList.add("samir");
nameList.add("swastika");
}

Optional<String> findName(Optional<String> name){
return name.isPresent()?Optional.of(nameList.get(nameList.indexOf(name.get().toLowerCase()))):Optional.empty();
}

public static void main(String[] args) {
OptionalTest optionalTest = new OptionalTest();
Optional<String> searchedNameOptional = optionalTest.findName(Optional.of("Shamik"));
if(searchedNameOptional.isPresent()) {
System.out.println(searchedNameOptional.get());
}
searchedNameOptional.ifPresent(System.out::println);

}

}


Here, I replaced the isPresent with ifPresent.

The flatmap function works the same as the map function, i.e. change one data structures to another data structure. But, if the return data structure holds an Optional, it does not create a nested Optional Structure Optional<Optional<T>>, it just returns Optional<T>.

For more, check out the following example:

package com.example.optional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class OptionalTest {

public void flatMapTest(String name) {
Optional<String> retName = Optional.of(name).flatMap(val->Optional.of(val));
System.out.println(retName);
}


public static void main(String[] args) {
OptionalTest optionalTest = new OptionalTest();
optionalTest.flatMapTest("Shamik");
}

}


In the FlatMap function, I deliberately returned the Optional.of(), and as the flatMap returns Optional<T>, it should then be Optional<Optional<String>>, but it only returns:

Optional<String> if we use map function we got Optional<Optional<String>>

We can use the filter function on Optional, so we can filter the value based on some criteria:

package com.example.optional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class OptionalTest {

private static List<String>nameList = new ArrayList<String>();

static {
nameList.add("shamik");
nameList.add("samir");
nameList.add("swastika");
}

Optional<String> findName(Optional<String> name){
return name.isPresent()?Optional.of(nameList.get(nameList.indexOf(name.get().toLowerCase()))):Optional.empty();
}


public static void main(String[] args) {
OptionalTest optionalTest = new OptionalTest();
Optional<String> searchedNameOptional = optionalTest.findName(Optional.of("Shamik"));
searchedNameOptional.filter(val->val.contains("am")).ifPresent(System.out::println);

}

}


PO: Master, I just learned so many important functions of Optional. Is there anything left to know about Optional?

OogWay: Yes, PO. We have covered a vast majority of the things you should know, but there is one more thing: why Optional is not serializable. However, I think this enough on Optionals for one day. I will give you the answer at a later date. I want you to think about it on your own, first. 

PO: Ok. Thank you, Master.

Java (programming language) Advice (programming)

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Writing a Modern HTTP(S) Tunnel in Rust
  • Deploying Java Serverless Functions as AWS Lambda
  • Automated Performance Testing With ArgoCD and Iter8
  • How To Generate Code Coverage Report Using JaCoCo-Maven Plugin

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: