finner

finner

Using Optional in Java

During a recent code review I came across this scenario:

Code in review

if (input.getValue() != null) {
   return Arrays.asList(value);
}  else {
   return input.getValues().stream().map(this::parseValues).collect(Collectors.toList())
}

And I suggested (in a compassionate way :grin: ) that we use Optional to treat the null value, so my suggestion was something like:

return Optional.ofNullable(input.getValue()).map(Arrays::asList)
       .orElseGet(input.getValues().stream().map(this::parseValues).collect(Collectors.toList()));

And I thought I was being very clever.

But then I realised it’s harder to understand the logic in this version. At least the if is a clear intent.
So I read up some more on Optional.
The Optional container allows us to perform logic including chaining map, flatMap, filter etc based on a value that may or may not be present. But this is not the real intention of Optional.

Optional is mainly used to represent attributes in an object that may be null or a method in an API that could return a null.

Consider a Person.
Everyone has a name, an age and a gender but may not have a car so we could define a class as follows:

class Person {
   private String name;
   private int age;
   private boolean female;
   private Optional<Car> car;
}

From this declaration it’s obvious that not everyone has a car and so the caller would then treat the car attribute appropriately.

My take away is the following:

Optional is not a replacement for occurrences if (x != null)

Any heavy users of Optional around?
Tips and/or suggestions would be very much appreciated.

Most Liked

finner

finner

Today I came across a very elegant use (IMHO) of Optional at work.
Consider the same person as above with a date of birth attribute:

public class Person {
   private String name;
   private String dob;

   // getters & setters etc etc (yep Java is verbose !!!!)
}

Now say you want to get that dob value into a Date object and do weird and wonderful date calculations.
You could use Optional like this:


// if you expect dob to be a string in the format yyyy-mm-dd
LocalDate birthday = Optional.ofNullable(persone.getDob())
    .map(LocalDate::parse)
    .orElse(null);  // or whatever

// or if the dob is in a different format, for example dd-MM-yyyy
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
LocalDate  d = Optional.ofNullable(p.getDob())
                .map(dob -> LocalDate.parse(dob, formatter))
                .orElse(null);

Now you have a LocalDate instance to play with.

In fact, once you have an Optional instance you have the following stream operators available

  • map
  • flatMap
  • filter

flatMap can be used to compose Optionals

public int ageDifference(Optional<Person> older, Optional<Person> younger) {
     return older.flatMap(o -> younger.map(y -> calAgeDifference(o.getDob(), y.getDob())); 
}

Quite cool :sunglasses:

Just thought I’d share :slight_smile:

finner

finner

cheers @AstonJ -
it’s actually good practice for me to help reinforce the learning by posting. Although at my age I will have forgotten it by end of week.
… so what were we talking about again … ?

AstonJ

AstonJ

:rofl: :rofl: :rofl:

I am just as bad - though I think a modern world is partly to blame - we are bombarded with information almost constantly now, imagine living a few thousand years ago before TV/Radio/Computers/Internet. Probably would have been quite serene and peaceful :smiley:

Funny thing is I read that article… and forgot most of it :rofl:

Where Next?

Popular Backend topics Top

bot
A new item has been posted: This thread was posted automatically, if you feel it could be in a better category and are at Trust Level ...
New
New
bot
Announcing the Error Handling Project Group | Inside Rust Blog. Want to follow along with Rust development? Curious how you might get in...
New
DevotionGeo
How Dgraph was running out of memory for some users, and how Go’s Garbage collector wasn’t enough, and Dgraph team used jemalloc to manag...
New
First poster: bot
About Self Self is a prototype-based dynamic object-oriented programming language, environment, and virtual machine centered around the p...
New
First poster: bot
Welcome to RETRO, my personal take on the Forth language. This is a modern system primarily targetting desktop, mobile, and servers, th...
New
mafinar
So I was thinking of trying out Crystal, I had tried it multiple times but left it midway. Now that there’s a book on it and it’s version...
New
DevotionGeo
What do you people do for reading Erlang docs? Is there something like Ruby’s ri? I installed manual pages for Erlang under /usr/local/...
New
AstonJ
And the blog: Rails has been unapologetically full stack since the beginning. We’ve continuously sought to include ever-more default an...
New
KnowledgeIsPower
MongoDB, Cassandra, DynamoDB and etc. Also, do you use VM or container to run it?
New

Other popular topics Top

AstonJ
A thread that every forum needs! Simply post a link to a track on YouTube (or SoundCloud or Vimeo amongst others!) on a separate line an...
New
AstonJ
What chair do you have while working… and why? Is there a ‘best’ type of chair or working position for developers?
New
ohm
Which, if any, games do you play? On what platform? I just bought (and completed) Minecraft Dungeons for my Nintendo Switch. Other than ...
New
DevotionGeo
I know that these benchmarks might not be the exact picture of real-world scenario, but still I expect a Rust web framework performing a ...
New
Exadra37
Please tell us what is your preferred monitor setup for programming(not gaming) and why you have chosen it. Does your monitor have eye p...
New
DevotionGeo
I know that -t flag is used along with -i flag for getting an interactive shell. But I cannot digest what the man page for docker run com...
New
dimitarvp
Small essay with thoughts on macOS vs. Linux: I know @Exadra37 is just waiting around the corner to scream at me “I TOLD YOU SO!!!” but I...
New
PragmaticBookshelf
Learn different ways of writing concurrent code in Elixir and increase your application's performance, without sacrificing scalability or...
New
AstonJ
Continuing the discussion from Thinking about learning Crystal, let’s discuss - I was wondering which languages don’t GC - maybe we can c...
New
AstonJ
This is a very quick guide, you just need to: Download LM Studio: https://lmstudio.ai/ Click on search Type DeepSeek, then select the o...
New