Collections - Should their getters return Optional?
-
1 -
-
Number of slices to send:Optional 'thank-you' note:
-
-
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
-
1 -
-
Number of slices to send:Optional 'thank-you' note:
-
-
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.
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
Do you mean Brian Goetz?Paul Clapham wrote:. . . somebody who was actually involved in the design of Optional. . . .
That SO thread also quotes Raoul-Garbiel Urma's opinions. I know the two of them have slightly different opinions. It is worth reading both those links.
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
All things are lawful, but not all things are profitable.
-
1 -
-
Number of slices to send:Optional 'thank-you' note:
-
-
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.

-
1 -
-
Number of slices to send:Optional 'thank-you' note:
-
-
There are three kinds of actuaries: those who can count, and those who can't.
-
1 -
-
Number of slices to send:Optional 'thank-you' note:
-
-
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
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.
There are three kinds of actuaries: those who can count, and those who can't.
-
1 -
-
Number of slices to send:Optional 'thank-you' note:
-
-
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.
Tim Driven Development | Test until the fear goes away
-
3 -
-
Number of slices to send:Optional 'thank-you' note:
-
-
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.
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
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.
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
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, "".
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
That reminds me of Eiffel; you can declare references as attached (nulls not permitted) or detached (nulls permissible).Junilu Lacar wrote:. . . . Kotlin . . . an Int? can be null whereas an Int cannot. . . .
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
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).
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
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. 
-
-
Number of slices to send:Optional 'thank-you' note:
-
-
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 |











