• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Devaka Cooray
  • Campbell Ritchie
  • Tim Cooke
  • Ron McLeod
  • Paul Clapham
Sheriffs:
  • Liutauras Vilda
  • Jeanne Boyarsky
  • paul wheaton
Saloon Keepers:
  • Tim Holloway
Bartenders:

Collections - Should their getters return Optional?

 
Ranch Hand
Posts: 143
6
IntelliJ IDE Eclipse IDE Java
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Java collections or data structures often have a method to get a specific element in that collection. Such methods often return null if the element is not present in the collection. For example, Map.get(Object key) returns null if the map contains no mapping for the key. Should these methods be upgraded to return an Optional instead ? Why ?

After reading the Oracle tutorial, I think we should do it. Just like the example below, we won't need to do null checks if Collections "getter" methods returned an Optional instead of null. But, I am not sure of my reasoning. Please advise.

With an Optional object, you can access the methods available to explicitly deal with the presence or absence of values, instead of having to remember to do a null check.





Some reference - https://stackoverflow.com/questions/26327957/should-java-8-getters-return-optional-type
 
Marshal
Posts: 28492
113
Eclipse IDE Firefox Browser MySQL Database
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm impressed by that SO thread because the highest-rated response is by somebody who was actually involved in the design of Optional.

However changing the method Map<T>.get(key) to return Optional<T> instead of T wouldn't be "upgrading", it would be "breaking". The people who design and build the Java language try very very hard to not make changes which would cause existing code to suddenly fail to compile. And that particular change would cause millions of people's code to fail to compile.

So it isn't going to happen, even if it's a good idea. But for new code, be it standard Java API or code written by you and me, there's certainly a place for Optional and it should be seriously considered.
 
Marshal
Posts: 81615
593
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Paul Clapham wrote:. . . somebody who was actually involved in the design of Optional. . . .

Do you mean Brian Goetz?
That SO th‍read also quotes Raoul-Garbiel Urma's opinions. I know the two of them have slightly different opinions. It is worth reading both those links.
 
Sheriff
Posts: 7126
185
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
What about a wrapper class OptionalHashMap that extends HashMap and overrides get(Object)?
 
Rancher
Posts: 5250
85
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Knute Snortum wrote:What about a wrapper class OptionalHashMap that extends HashMap and overrides get(Object)?



When overriding, you can't change the return type except to make it a more specific subtype.  So a get() that returns Object can be overridden with a get that returns String, for example.  But an Optional<Foo> is not a subtype of Foo, or a subtype of anything other than Object and Optional.  So the only way your get() could return an Optional<Foo> while implementing a Map<E> interface is if it's a Map<Optional<Foo>>.  Which in turn means you'd need to do things like

And I don't think anyone wants that.

We could certainly imagine a new OptionalMap interface that is similar to Map, but not a subtype of Map.  That might be a better approach.  That way we could have


Or, we could just use Kotlin.
 
Bartender
Posts: 5752
217
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I don't use Optionals often, but if you want: why not extend a HashMap? For instance


 
Mike Simmons
Rancher
Posts: 5250
85
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes, that would work.  But it would also leave the original get() method exposed, which would still potentially return null, and not an Optional.  It's not the end of the world to have two methods, both get() and getOptional()... but I personally think it's more confusing. If you want a class that uses Optional to force users to deal with the fact that the thing they want to get() may not be there... it seems like an oversight to leave a get() method that completely bypasses that goal.  But, it can be done...
 
Piet Souris
Bartender
Posts: 5752
217
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
At least it gives the user a choice  

Another possibility is to overload the get method, say get(key, optional = true). But the trouble of getting this to work for all kinds of Maps far outweights a possible benefit, in my humble opinion.
 
Marshal
Posts: 6209
501
IntelliJ IDE Python TypeScript Java Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Personally I wouldn't bother meddling with the Collection and Map interfaces. You would suppose that if the Optional type existed from the start then it would be employed over returning null but the reality is that it didn't and the language designers value backwards compatibility enough that it is unlikely to ever change.

I use Optional quite liberally when writing classes that interact with a database or some other volatile data source where the absence of data is expected.
 
Paul Clapham
Marshal
Posts: 28492
113
Eclipse IDE Firefox Browser MySQL Database
  • Likes 3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I recently decided to do an experiment with using Optional to deal with a situation where there could be nulls flying around all over the place. Originally I had some code which looked like this:



And my re-write using Optional looked like this:



Needless to say I wasn't sure that was an improvement. And I'm not sure that the indentation style I used there is the best choice either.

 
Campbell Ritchie
Marshal
Posts: 81615
593
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
How would you have written that code with nested ?:s?
 
Sheriff
Posts: 17735
302
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Interesting topic, and seldom one you see in Beginning Java. Kudos to OP for thinking about this.

See also: https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare/

Knute Snortum wrote:What about a wrapper class OptionalHashMap that extends HashMap and overrides get(Object)?


You pretty much have to resort to that. Or put a whole 'nother language on top of the JVM. Kotlin has its own way of dealing with nulls: use the type system to clearly delineate nullable values from non-nullable values. A variable declared as an Int? can be null whereas an Int cannot. As far as I can tell, Int? and Int are two distinct types and the syntax forces you to make a conscious choice to use one or the other. Syntax also forces you to make a conscious effort to assign one type of value to the other.

Tim Cooke wrote:You would suppose that if the Optional type existed from the start then it would be employed over returning null but the reality is...


The reality is that even with the introduction of Optional, there are still many laggards who haven't incorporated it into their toolset or newer designs. Good for you for doing that but it takes a bit of effort to understand the benefits of not dealing with nulls. Studying Kotlin is starting to drive that idea home for me now. But even Kotlin had to make accommodations for making nullable and non-nullable values play nicely together. This is from an exercise I've been working on (FlashCards)

On line 3, the expression deck[card]!! basically says "the value for the key card--and yes(!!), I know that technically, deck[card] could be null but I know it won't be here." The !! is kind of like a null cast that assures the compiler that the value won't be null. Same deal on line 12. The thing is that if you're just being sloppy and the value does turn out to be null after all, then an NPE will come back and bite you.

And then there's the "Elvis operator", ?:, and the Kotlin idiom on line 17. That's basically this in Java:

So, yeah, it's a little bit more effort to deal with nulls.
 
Junilu Lacar
Sheriff
Posts: 17735
302
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Paul Clapham wrote:

... And I'm not sure that the indentation style I used there is the best choice either.


Looks fine to me. That's probably what I would have done, too, although that doesn't necessarily mean anything one way or the other

I think this highlights the design mindset shift you have to make between "How do I easily deal with nulls and give sensible defaults here?" to "What are sensible defaults here?"

For example, in Kotlin, the mindset is turned the other way and that would have been handled in the method signature:

although I'm not sure why it would be two spaces instead of just an empty string, "".
 
Campbell Ritchie
Marshal
Posts: 81615
593
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Junilu Lacar wrote:. . . . Kotlin . . . an Int? can be null whereas an Int cannot. . . .

That reminds me of Eiffel; you can declare references as attached (nulls not permitted) or detached (nulls permissible).
 
Paul Clapham
Marshal
Posts: 28492
113
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Junilu Lacar wrote:although I'm not sure why it would be two spaces instead of just an empty string, "".



My code standardizes the language and country codes to exactly two characters in length (for some reason lost in the mists of antiquity).
 
Mike Simmons
Rancher
Posts: 5250
85
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Under Java 8 think I'd render Paul's code as

It's ugly, but the increasing indentation helps me understand what it's really doing.

Under Java 9+, it can become

or

And the Kotlin equivalent would be

or maybe

(if you're sure the last one will not be null)

Going back to Java 8, a few years ago I disliked the original Optional way enough to write something like this:

Then we can write:
     

After all that though, it's worth remembering that from the earliest public version of Java, you could simply write


The only reason I went to firstNonNull() was because I was replacing a bunch of code with variables that (a) were final, and (b) had unbearably long names.  And I was getting tired of explaining myself in code reviews.   We had a lot of logic like this.
 
Paul Clapham
Marshal
Posts: 28492
113
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:Under Java 9+, it can become



I'm going to use that instead.

When I did the Optional exercise I was still using Java 8, so that version wasn't available. But no excuse, I'm on Java 13 now and I didn't know about that method.

There's a lot that happened since Java 8 that I didn't know, too. Like for example somebody changed the inner workings of the LocalDate.parse(date, formatter) method to work differently for different locales. It didn't used to work that way but now apparently Canadians use "Mar." to abbreviate March and Americans use "Mar", so I have to tell the formatter that I want it to use the US locale. I'm really going to have to hunt down all of the release notes and read them.
 
We can walk to school together. And we can both read this tiny ad:
Paul Wheaton's 16th Kickstarter: Gardening playing cards for gardeners and homesteaders
https://coderanch.com/t/889615/Paul-Wheaton-Kickstarter-Gardening-playing
reply
    Bookmark Topic Watch Topic
  • New Topic