RFR 8080418 Add Optional.or()

Tagir F. Valeev amaembo at gmail.com
Fri Sep 25 12:00:11 UTC 2015


Quite interesting and long awaited features (at least according to
StackOverflow questions). Isn't it a good idea to provide also a way
to transfer between Optional types like "mapToInt", "mapToObj", etc.,
like it's done in Stream API?

PS> 2) add to all variants a mapOrElseGet (otherwise known as a
PS> “fold”), which is the equivalent of
PS> map(mapper).orElseGet(supplier). That is arguably less
PS> mind-bending to use when transforming from Optional<T> to Optional<U>.

The proposed implementation is the following:

    public<U> U mapOrElseGet(Function<? super T, ? extends U> mapper,
                             Supplier<? extends U> supplier) {
        if (!isPresent()) {
            return supplier.get();
        } else {
            return mapper.apply(value);

It documents that:

     * @throws NullPointerException if the mapping function or the supplying
     *         function is {@code null}

However in fact it throws not always. For example, this call will not

  Optional.empty().mapOrElseGet(null, () -> "x");

To me it seems that this should be fixed (possibly adding
requireNonNull checks) as it could become the source of silent bugs.
Also you say that it's equivalent to the map().orElseGet() chain.
However this one throws:

  Optional.empty().<String>map(null).orElseGet(() -> "x");

There's also another problem. The orElseGet(null) is documented to
work to work fine for non-empty optional (why on the Earth it was
specified this way?). So there's good question whether the "supplier"
argument of "mapOrElseGet" should be allowed to be null for non-empty
optional (to conform with "orElseGet") or should not be allowed (to
conform with "mapper" argument).

With best regards,
Tagir Valeev.

More information about the core-libs-dev mailing list