43

As a primitive version of Optional*, Java 1.8 provides OptionalInt, OptionalLong and OptionalDouble.

But I cannot find the equivalent OptionalBoolean class.

Are there any technical reasons against having an OptionalBoolean?

* An Optional may or may not have the presence of a value, is used as an alternative to null.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
Martin Andersson
  • 18,072
  • 9
  • 87
  • 115
  • 1
    I suppose we could ask the same question about why `OptionalChar`, `OptionalByte`, `OptionalShort`, and `OptionalFloat` are also missing. – rgettman May 28 '14 at 21:29
  • Edited in the second question, as the other question cannot be answered by anybody but Oracle. – Maarten Bodewes May 28 '14 at 21:31
  • I *definitely* remember reading something about this. If memory serves, it had to do with the fact that everything "fits" into an `int`, `long`, and `double`, so the other ones would be redundant. – awksp May 28 '14 at 21:33
  • I was just thinking that `OptionalInt` "kind of" covers for `OptionalByte`, `OptionalShort`, and `OptionalChar`. The `int` in a `OptionalInt` might overflow on the client side, but in every day code authorship, we are used to making these conversions. Not as much though going from an `int` to a `boolean`. I would very much like to see a `OptionalBoolean`. – Martin Andersson May 28 '14 at 21:39
  • 4
    [This question](http://stackoverflow.com/questions/22918847/why-are-new-java-util-arrays-methods-in-java-8-not-overloaded-for-all-the-primit) is related. – Eran May 28 '14 at 21:53
  • @Eran That's what I was searching for! Brian Goetz's quote answers this question perfectly. – awksp May 28 '14 at 21:55
  • That is it. If you google the text for "Trick #1", you'll find what I would accept as an answer to my question, that it was a tradeof made to keep the type explosion down to a minimum. One of you should add an answer so that I can accept it. – Martin Andersson May 28 '14 at 22:04
  • 1
    @user3580294 Well, the quote is about primitive streams, but I assume the same logic applied to primitive Optionals. – Eran May 28 '14 at 22:04
  • Yup, good answer, but it cannot be definitive as the question does not allow for definitive answers - unless Brian gives us a visit :) – Maarten Bodewes May 28 '14 at 22:05
  • owlstead, I don't believe any question can have a definitive answer. But I see your point. – Martin Andersson May 28 '14 at 22:09
  • 6
    For the one trying to close this as a dupe: a duplicate answer does not mean a duplicate question has been raised. – Maarten Bodewes May 28 '14 at 22:09
  • 1
    Related http://stackoverflow.com/a/28738297/57695 – Peter Lawrey Feb 26 '15 at 09:13

4 Answers4

19

This quote explains the considerations behind having primitive streams. I'm assuming the same applied to primitive Optionals. In short, primitive streams (and probably Optionals as well) were created for performance reasons. They didn't create them for all 8 primitive types to reduce code duplication and interface pollution.

Quoting the words of Brian Goetz in the lambda mailing list:

More generally: the philosophy behind having specialized primitive streams (e.g., IntStream) is fraught with nasty tradeoffs. On the one hand, it's lots of ugly code duplication, interface pollution, etc. On the other hand, any kind of arithmetic on boxed ops sucks, and having no story for reducing over ints would be terrible. So we're in a tough corner, and we're trying to not make it worse.

Trick #1 for not making it worse is: we're not doing all eight primitive types. We're doing int, long, and double; all the others could be simulated by these. Arguably we could get rid of int too, but we don't think most Java developers are ready for that. Yes, there will be calls for Character, and the answer is "stick it in an int." (Each specialization is projected to ~100K to the JRE footprint.)

Trick #2 is: we're using primitive streams to expose things that are best done in the primitive domain (sorting, reduction) but not trying to duplicate everything you can do in the boxed domain. For example, there's no IntStream.into(), as Aleksey points out. (If there were, the next question(s) would be "Where is IntCollection? IntArrayList? IntConcurrentSkipListMap?) The intention is many streams may start as reference streams and end up as primitive streams, but not vice versa. That's OK, and that reduces the number of conversions needed (e.g., no overload of map for int -> T, no specialization of Function for int -> T, etc.)

And I should mention that I found that quote in the answer to this question.

Community
  • 1
  • 1
Eran
  • 387,369
  • 54
  • 702
  • 768
6

boolean values are often abused as parameters. Effective Java 2nd edition warns against abuse of booleans. They often lead to badly readable code if they are not for actual boolean true/false arguments. Instead, Joshua Bloch - the writer - tries to convince people to use double valued enum's:

Prefer two-element enum types to boolean parameters. It makes your code easier to read and to write, especially if you're using an IDE that supports autocompletion. Also it makes it easy to add more options later.

Most OptionalBoolean instances would probably be used incorrectly. This is a good reason for not including one. But I cannot say - only Oracle can - if this is the reason why it is not in there.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • 3
    So has it become Oracle's policy to omit language features that might possibly be misused? Kind of disappointing, although I don't care specifically about the absence of OptionalBoolean. It's just as well that the makers of machine language didn't have such a policy - we'd have just 0s and no 1s. – Dawood ibn Kareem May 28 '14 at 21:45
  • I love that book, and I respect Joshua very much. I also think you have a point. When Joshua described good ways of overriding and implementing `Object.equals(Object)` in that book, he said that one must always use the `instanceof` operator and called the use of `getClass()` for being "unacceptable" (page 39). I've also noticed that all library code in Oracle's implementation is using the `instanceof` operator. I haven't found one example of the `getClass()` operator (which happens to be my favorite in non-library code). So a quote from Joshua on the topic would be really valuable. – Martin Andersson May 28 '14 at 21:46
  • I agree with you, and I do prefer `enum` over `boolean` values as "options" to a method call. What I would need is a tri-state boolean though, one that can represent an "any" or "inconclusive" state. And I hate nulls ever since Java 1.8 =) – Martin Andersson May 28 '14 at 21:55
  • @owlstead Checked exceptions anyone? – phs May 28 '14 at 22:01
  • @Eran up on the question comments found another question whose accepted answer would likely answer this question. tl;dr: [this](http://mail.openjdk.java.net/pipermail/lambda-dev/2012-November/006750.html) – awksp May 28 '14 at 22:03
3

Apart for the desire to reduce the magnitude of the combinatorial explosion of primitive type specialisation classes I suspect one major reason for the absence of an OptionalBoolean is that the advantage of such a class is much smaller than the advantage of specialisations for the numeric types.

The reason for why the advantage is smaller is that there are only two different values of the type boolean. Because of this, most of the time you only get two object of type Boolean. Those two are cached as Boolean.TRUE and Boolean.FALSE and reused in most cases, e.g. when booleans are auto-boxed. Numeric wrapper types have a number of cached objects for a small range of values, for other values a new object has to be allocated every time a primitive value is stored in a generic container such as Optional.

So an Optional<Boolean> object is almost as efficient as an OptionalBoolean would be since no new Boolean have to be allocated to put an unboxed boolean into it.

I could also be useful to have two cashed Optional<Boolean> available somewhere in the standard library, as Optional.TRUE/FALSE perhaps. I don't know the reason for why there isn't.

Lii
  • 11,553
  • 8
  • 64
  • 88
  • `Boolean` will not be allocated, but `Optional` will be. Compared with `OptionalBoolean` implementation, which can be implemented as an enum of `{oTrue, oFalse, none}`, this still would have bigger memory footprint. – M. Prokhorov Jan 15 '18 at 11:32
2

Just to be complete about that: There is indeed an OptionalBoolean in Java 8, but not where you would expect it: it is com.sun.javafx.scene.control.behavior.OptionalBoolean.

But, while JavaFX is nowadays a fixed component of Java, it is not advisable to use it outside of JavaFX stuff.

Apart from that, its interface is completely different from the ones you have in java.util.*.

glglgl
  • 89,107
  • 13
  • 149
  • 217
  • 3
    Not sure if this should be a comment instead, but whatever it is, it's definitely a good warning for those relying on completion in IDE's such as Eclipse, NetBeans and similar. – Maarten Bodewes Feb 12 '16 at 12:55