12

In Java8 streams I can use the mapToInt method to create an IntStream, which will return OptionalInts for some actions (like findFirst). Why isn't there anything similar in Optional?

int i = Stream
        .of("1") // just as an example
        .mapToInt(Integer::parseInt) // mapToInt exists for streams
        .findFirst() // this even returns an OptionalInt!
        .getAsInt(); // quite handy

int j = Optional
        .of("1") // same example
        .map(Integer::parseInt) // no mapToInt available
        .get().intValue(); // not as handy as for streams
slartidan
  • 20,403
  • 15
  • 83
  • 131
  • 4
    This is a quote from Brian Goetz: "The set of "obvious" methods requested to be added to Optional is seemingly infinite". http://stackoverflow.com/questions/28796324/optional-vs-throwing-an-exception – Paul Boddington Oct 02 '15 at 13:45
  • Because `OptionalInt` and other special-case methods exists only to avoid many boxing/unboxing operations. – user11153 Oct 02 '15 at 13:45
  • 3
    Why is `.getAsInt()` so much better than `.get().intValue()`? And what about simply calling `get()`, omitting the obsolete `intValue()` call? – Holger Oct 02 '15 at 14:04

3 Answers3

9

Apparently a handful of additional methods will appear in Optionals in Java-9. However it's unlikely that mapToInt will be added. I discussed this problem several days before in core-libs-dev. Here's Paul Sandoz answer:

I don’t wanna go there, my response is transform Optional* into a *Stream. An argument for adding mapOrElseGet (notice that the primitive variants return U) is that other functionality can be composed from it.

And later:

I think it’s fine to to pollute OptionalInt etc with Optional but i want to avoid it for the other direction.

In general I think it's reasonable. The purpose of primitive streams is to improve the performance when you process many primitive values. However for Optional the performance gain of using the primitive value is quite marginal if any (there are much bigger chances compared to streams that extra boxing will by optimized out by JIT-compiler). Also even though project Valhalla will not appear in Java-9, it's gradually moving forward and it's possible that in Java-10 we will finally see generics-over-primitives, so these primitive optionals will become completely unnecessary. In this context adding more interoperability between Object Optional and primitive OptionalInt seems unnecessary.

Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
8

It makes sense to have specializations in the Stream API as a stream may represent bulk operations processing millions of elements, thus the performance impact can be dramatic. But as far as I know, even this decision wasn’t without a controversy.

For an Optional, carrying at most one element, the performance impact is not justifying additional APIs (if there ever is an impact). It’s not quite clear whether OptionalInt, etc. are really necessary at all.

Regarding the convenience, I can’t get your point. The following works:

int j = Optional.of("1").map(Integer::parseInt).get();

your proposal is to add another API which allows to rewrite the above statement as

int j = Optional.of("1").mapToInt(Integer::parseInt).getAsInt();

I don’t see how this raises the convenience…

But following the logic, with Java 9, you can write

int j = Optional.of("1").stream().mapToInt(Integer::parseInt).findFirst().getAsInt();

which raises this kind of “convenience” even more…

Holger
  • 285,553
  • 42
  • 434
  • 765
-1

The following also works quite nicely:

int j = Optional
        .of("1")
        .map(Integer::parseInt)
        .map(OptionalInt::of)         // -> Optional<OptionalInt>
        .orElse(OptionalInt.empty())  // -> OptionalInt
        .getAsInt();

The trick is to map Optional<Integer> to Optional<OptionalInt> and then unwrap the inner OptionalInt. Thus, as far as the Optional is concerned, no primitive int is involved, so it works with Java generics.

One advantage of this approach is that it doesnt need autoboxing. That's an important point for me as we enabled warnings for autoboxing in our project, primarily to prevent unnecessary boxing and unboxing operations.

I stumbled upon this problem and the solution while implementing a public method that returns an OptionalInt, where the implementation uses another method returning Optional<Something>. I didn't want to return Optional<Integer> from my public method, so I searched for something like Optional.mapToInt just like you.

But after reading the responses of Holger and Tagir Valeev, I agree that it's perfectly reasonable to omit such a method in the JDK. There are enough alternatives available.

mperktold
  • 436
  • 4
  • 14