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
Partner Zones AWS Cloud
by AWS Developer Relations
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
Partner Zones
AWS Cloud
by AWS Developer Relations
The Latest "Software Integration: The Intersection of APIs, Microservices, and Cloud-Based Systems" Trend Report
Get the report
  1. DZone
  2. Coding
  3. Java
  4. Java 8 Optional—Replace Your Get() Calls

Java 8 Optional—Replace Your Get() Calls

If we still use the get() functionality on optionals, we're effectively opening ourselves to the same problems as null checks. Here's how we should properly use this new tool in our arsenal.

Mario Pio Gioiosa user avatar by
Mario Pio Gioiosa
CORE ·
Jul. 05, 16 · Tutorial
Like (87)
Save
Tweet
Share
122.37K Views

Join the DZone community and get the full member experience.

Join For Free

Optional classes were introduced in order to prevent NullPointerException, but the method get() used to retrieve the value inside the Optional might still throw a NoSuchElementException.

Different name, same issue?

Calling get() without checking that value is actually present it’s a bug. So we should always write something like that in order to use get().\

Optional<String> myString = Optional.ofNullable(getNullableString());
if(myString.isPresent()){
    doSomething(myString.get());
}

But are Optional really meant to be used in this way? No.

Writing block of isPresent/get it’s not so different from writing a classic null check.

String myString = getNullableString();
if(myString != null){
    doSomething(myString);
}

Let’s see how we can really benefit from Optional object.

1. Optional orElse Example

It returns the value if is present, or the other specified otherwise.

Let’s see an example:

@Test
public void orElse_whenNamePresent_ThenName(){
    Optional<String> petName = Optional.of("Bobby");

    assertEquals("Bobby", petName.orElse(""));
}

@Test
public void orElse_whenNameNotPresent_ThenEmptyString(){
    Optional<String> petName = Optional.empty();

    assertEquals("", petName.orElse(""));
}

As you can see we haven’t called get() and we’ve made the code easier and more readable compared to the isPresent/get version:

@Test
public void isPresentGet_whenNamePresent_ThenName(){
    Optional<String> petNameOptional = Optional.of("Bobby");

    String petName = "";
    if(petNameOptional.isPresent()){
        petName = petNameOptional.get();
    } 

    assertEquals("Bobby", petName);
}

@Test
public void isPresentGet_whenNameNotPresent_ThenEmptyString(){
    Optional<String> petNameOptional = Optional.empty();

    String petName = "";
    if(petNameOptional.isPresent()){
        petName = petNameOptional.get();
    } 

    assertEquals("", petName);
}

2. Optional orElseThrow Example

It returns the value if is present, or throws the specified exception otherwise.

@Test
public void orElseThrow_whenNamePresent_ThenName(){
    Optional<String> petName = Optional.of("Bobby");

    assertEquals("Bobby", petName.orElseThrow(""));
}

@Test(expected=IllegalArgumentException.class)
public void orElseThrow_whenNameNotPresent_ThenIllegalArgEx(){
    Optional<String> petName = Optional.empty();

    petName.orElseThrow(IllegalArgumentException::new);
}

3. Optional filter Example

filter() is useful to specify other conditions on our object. It returns an Optional containing the value if is not empty and satisfy the specified predicate, an empty Optional otherwise.

In this example we want that the name not only is different from null but also that is not empty or made of only empty spaces.

@Test
public void filter_whenNameNotEmpty_thenName(){
    Optional<String> petNameOpt = Optional.of("Bobby");

    String petName = petNameOpt.filter(name -> !name.trim().isEmpty())
       .orElseThrow(IllegalArgumentException::new);

    assertEquals("Bobby", petName);
}

And those are the tests for the null and the empty name:

@Test(expected=IllegalArgumentException.class)
public void filter_whenNameNotPresent_thenIllegalArgEx(){
    Optional<String> petNameOpt = Optional.empty();

    petNameOpt.filter(name -> !name.trim().isEmpty())
      .orElseThrow(IllegalArgumentException::new);
}

@Test(expected=IllegalArgumentException.class)
public void filter_whenNameEmpty_thenIllegalArgEx(){
    Optional<String> petNameOpt = Optional.of(" ");

    petNameOpt.filter(name -> !name.trim().isEmpty())
      .orElseThrow(IllegalArgumentException::new);
}

4. Optional ifPresent Example

IfPresent, that it’s different from isPresent, accept a function, a Consumer, and executes it only if the value is present.

So instead of writing something like:

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

You can write:

optional.ifPresent(val->doSomething(val))

or if you prefer:

optional.ifPresent(this::doSomething)

But let’s have a look to a proper example.

We define a Pojo class, useful also for the following examples, that represents a Loyalty card.

public class LoyaltyCard {

    private String cardNumber;

    private int points;

    public LoyaltyCard(String cardNumber, int points){
        this.cardNumber = cardNumber;
        this.points = points;
    }

    public int addPoints(int pointToAdd){
        return points += pointToAdd;
    }

    //Getters

}

We want to add 3 points to the loyalty card if loyalty card is actually present.

Node: In the following example we’re going to use Mockito to mock LoyaltyCard class. Don’t worry if you are not familiar with Mockito, I’ll add some comments to the code.

@Test
public void ifPresent_whenCardPresent_thenPointsAdded(){
    LoyaltyCard mockedCard = mock(LoyaltyCard.class);
    Optional<LoyaltyCard> loyaltyCard = Optional.of(mockedCard);

    loyaltyCard.ifPresent(c -> c.addPoints(3));

    //Verify addPoints method has been called 1 time and with input=3
    verify(mockedCard, times(1)).addPoints(3);
}

5. Optional map Example

map() it’s a method that we use to transform an input in a different output. In this case nothing changes except that the map operation will be executed only if the value is actually present, otherwise it returns an empty Optional.

In this example we want to retrieve the number of points of our loyalty card if we have it, otherwise number of point will return 0.

@Test
public void map_whenCardPresent_thenNumber(){
    LoyaltyCard mockedCard = mock(LoyaltyCard.class);
    when(mockedCard.getPoints()).thenReturn(3);

    Optional<LoyaltyCard> card = Optional.of(mockedCard);

    int point = card.map(LoyaltyCard::getPoints)
       .orElse(0);

    assertEquals(3, point);
}

@Test
public void map_whenCardNotPresent_thenZero(){
    Optional<LoyaltyCard> card = Optional.empty();

    int point = card.map(LoyaltyCard::getPoints)
       .orElse(0);

    assertEquals(0, point);
}

@Test
public void map_whenCardNotPresent_thenZero(){
    Optional<LoyaltyCard> card = Optional.empty();

    int point = card.map(LoyaltyCard::getPoints)
       .orElse(0);

    assertEquals(0, point);
}

6. Optional flatMap Example

flatMap() it’s really similar to map() but when output is already an Optional it doesn’t wrap it with another Optional. So instead of having Optional<Optional<T>> if will just return Optional<T>.

Let me clarify it using an example. Let’s define a new class, called Gift.

public class Gift {

    private String name;

    // Constructor and getters

}

And let’s define a new method to our LoyaltyCard class that returns an Optional containing the last Gift chosen. Since we are going to mock the result of this method, we don’t really care about its implementation.

publicOptional<Gift>getLastGift(){

    //whatever

returnOptional.empty();

We can now create a mocked Gift with name “Biography of Guybrush Threepwood”, put it into an Optional and make getLastGift return it. So if we write:

card.map(LoyaltyCard::getLastGift)

Output will be an Optional<Optional<Gift>> that is not what we want, so flatMap will unwrap this double level and leave only an Optional<Gift>.

@Test
public void flatMap_whenCardAndLastGiftPresent_thenName(){
    Gift mockedGift = mock(Gift.class);
    when(mockedGift.getName()).thenReturn("Biography of Guybrush Threepwood");

    LoyaltyCard mockedCard = mock(LoyaltyCard.class);
    when(mockedCard.getLastGift()).thenReturn(Optional.of(mockedGift));
    Optional<LoyaltyCard> card = Optional.of(mockedCard);

    String giftName = card.flatMap(LoyaltyCard::getLastGift)
        .map(Gift::getName)
        .orElse("");

    assertEquals("Biography of Guybrush Threepwood", giftName);
}

Writing this solution by using isPresent/get would have meant using a nested if: one for check that card was present and another of checking the gift. Harder to read, easier to fail.

7. Optional ifPresentOrElse ?

Unfortunately this is yet to come It will be available in Java 9.

Until then we have to write something like:

if(optional.isPresent()){
    doSomething(optional.get());
} else {
    doSomethingElse();
}

There are cases in which you are allowed to use get() and isPresent() but use them with a grain of salt.

Java (programming language)

Published at DZone with permission of Mario Pio Gioiosa, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • The Power of Docker Images: A Comprehensive Guide to Building From Scratch
  • Building a RESTful API With AWS Lambda and Express
  • Test Execution Tutorial: A Comprehensive Guide With Examples and Best Practices
  • Use AWS Controllers for Kubernetes To Deploy a Serverless Data Processing Solution With SQS, Lambda, and DynamoDB

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: