RFE: add missing methods to Optional, OptionalInt, OptionalLong and OptionalDouble

Rob Spoor openjdk at icemanx.nl
Sat Feb 16 12:52:02 UTC 2019


I noticed that, while Stream and its primitive equivalents have multiple 
map and flapMap methods, Optional and its primitive equivalents were 
missing those. Since these can still be very useful, I wrote a patch to 
add the following methods:

* Optional: mapToInt, mapToLong, mapToDouble, flatMapToInt, 
flatMapToLong, flatMapToDouble
* OptionalInt: map, mapToObj, mapToLong, mapToDouble, flatMap
* OptionalLong: map, mapToObj, mapToInt, mapToDouble, flatMap
* OptionalDouble: map, mapToObj, mapToInt, mapToLong, flatMap

I did not add any more flatMap methods to OptionalInt, OptionalLong and 
OptionalDouble because these also don't exist on IntStream, LongStream 
and DoubleStream.


In addition, I also added the missing or method to OptionalInt, 
OptionalLong and OptionalDouble based on that of Optional.


My OCA has been processed on 2019-01-22.


Rob
-------------- next part --------------
diff --git a/src/java.base/share/classes/java/util/Optional.java b/src/java.base/share/classes/java/util/Optional.java
--- a/src/java.base/share/classes/java/util/Optional.java
+++ b/src/java.base/share/classes/java/util/Optional.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,9 @@
 import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.function.Supplier;
+import java.util.function.ToDoubleFunction;
+import java.util.function.ToIntFunction;
+import java.util.function.ToLongFunction;
 import java.util.stream.Stream;
 
 /**
@@ -267,6 +270,69 @@
     }
 
     /**
+     * If a value is present, returns an {@code OptionalInt} describing the
+     * result of applying the given mapping function to the value, otherwise
+     * returns an empty {@code OptionalInt}.
+     *
+     * @param mapper the mapping function to apply to a value, if present
+     * @return an {@code OptionalInt} describing the result of applying a
+     *         mapping function to the value of this {@code Optional}, if a
+     *         value is present, otherwise an empty {@code Optional}
+     * @throws NullPointerException if the mapping function is {@code null}
+     * @since 13
+     */
+    public OptionalInt mapToInt(ToIntFunction<? super T> mapper) {
+        Objects.requireNonNull(mapper);
+        if (!isPresent()) {
+            return OptionalInt.empty();
+        } else {
+            return OptionalInt.of(mapper.applyAsInt(value));
+        }
+    }
+
+    /**
+     * If a value is present, returns an {@code OptionalLong} describing the
+     * result of applying the given mapping function to the value, otherwise
+     * returns an empty {@code OptionalLong}.
+     *
+     * @param mapper the mapping function to apply to a value, if present
+     * @return an {@code OptionalLong} describing the result of applying a
+     *         mapping function to the value of this {@code Optional}, if a
+     *         value is present, otherwise an empty {@code Optional}
+     * @throws NullPointerException if the mapping function is {@code null}
+     * @since 13
+     */
+    public OptionalLong mapToLong(ToLongFunction<? super T> mapper) {
+        Objects.requireNonNull(mapper);
+        if (!isPresent()) {
+            return OptionalLong.empty();
+        } else {
+            return OptionalLong.of(mapper.applyAsLong(value));
+        }
+    }
+
+    /**
+     * If a value is present, returns an {@code OptionalDouble} describing the
+     * result of applying the given mapping function to the value, otherwise
+     * returns an empty {@code OptionalDouble}.
+     *
+     * @param mapper the mapping function to apply to a value, if present
+     * @return an {@code OptionalDouble} describing the result of applying a
+     *         mapping function to the value of this {@code Optional}, if a
+     *         value is present, otherwise an empty {@code Optional}
+     * @throws NullPointerException if the mapping function is {@code null}
+     * @since 13
+     */
+    public OptionalDouble mapToDouble(ToDoubleFunction<? super T> mapper) {
+        Objects.requireNonNull(mapper);
+        if (!isPresent()) {
+            return OptionalDouble.empty();
+        } else {
+            return OptionalDouble.of(mapper.applyAsDouble(value));
+        }
+    }
+
+    /**
      * If a value is present, returns the result of applying the given
      * {@code Optional}-bearing mapping function to the value, otherwise returns
      * an empty {@code Optional}.
@@ -297,6 +363,90 @@
     }
 
     /**
+     * If a value is present, returns the result of applying the given
+     * {@code OptionalInt}-bearing mapping function to the value, otherwise
+     * returns an empty {@code OptionalInt}.
+     *
+     * <p>This method is similar to {@link #mapToInt(ToIntFunction)}, but the
+     * mapping function is one whose result is already an {@code OptionalInt},
+     * and if invoked, {@code flatMapToInt} does not wrap it within an
+     * additional {@code OptionalInt}.
+     *
+     * @param mapper the mapping function to apply to a value, if present
+     * @return the result of applying an {@code OptionalInt}-bearing mapping
+     *         function to the value of this {@code Optional}, if a value is
+     *         present, otherwise an empty {@code OptionalInt}
+     * @throws NullPointerException if the mapping function is {@code null} or
+     *         returns a {@code null} result
+     * @since 13
+     */
+    public OptionalInt flatMapToInt(Function<? super T, ? extends OptionalInt> mapper) {
+        Objects.requireNonNull(mapper);
+        if (!isPresent()) {
+            return OptionalInt.empty();
+        } else {
+            OptionalInt r = mapper.apply(value);
+            return Objects.requireNonNull(r);
+        }
+    }
+
+    /**
+     * If a value is present, returns the result of applying the given
+     * {@code OptionalLong}-bearing mapping function to the value, otherwise
+     * returns an empty {@code OptionalLong}.
+     *
+     * <p>This method is similar to {@link #mapToLong(ToLongFunction)}, but the
+     * mapping function is one whose result is already an {@code OptionalLong},
+     * and if invoked, {@code flatMapToLong} does not wrap it within an
+     * additional {@code OptionalLong}.
+     *
+     * @param mapper the mapping function to apply to a value, if present
+     * @return the result of applying an {@code OptionalLong}-bearing mapping
+     *         function to the value of this {@code Optional}, if a value is
+     *         present, otherwise an empty {@code OptionalLong}
+     * @throws NullPointerException if the mapping function is {@code null} or
+     *         returns a {@code null} result
+     * @since 13
+     */
+    public OptionalLong flatMapToLong(Function<? super T, ? extends OptionalLong> mapper) {
+        Objects.requireNonNull(mapper);
+        if (!isPresent()) {
+            return OptionalLong.empty();
+        } else {
+            OptionalLong r = mapper.apply(value);
+            return Objects.requireNonNull(r);
+        }
+    }
+
+    /**
+     * If a value is present, returns the result of applying the given
+     * {@code OptionalDouble}-bearing mapping function to the value, otherwise
+     * returns an empty {@code OptionalDouble}.
+     *
+     * <p>This method is similar to {@link #mapToDouble(ToDoubleFunction)}, but
+     * the mapping function is one whose result is already an
+     * {@code OptionalDouble}, and if invoked, {@code flatMapToDouble} does not
+     * wrap it within an additional {@code OptionalDouble}.
+     *
+     * @param mapper the mapping function to apply to a value, if present
+     * @return the result of applying an {@code OptionalDouble}-bearing mapping
+     *         function to the value of this {@code Optional}, if a value is
+     *         present, otherwise an empty {@code OptionalDouble}
+     * @throws NullPointerException if the mapping function is {@code null} or
+     *         returns a {@code null} result
+     * @since 13
+     */
+    public OptionalDouble flatMapToDouble(Function<? super T, ? extends OptionalDouble> mapper) {
+        Objects.requireNonNull(mapper);
+        if (!isPresent()) {
+            return OptionalDouble.empty();
+        } else {
+            OptionalDouble r = mapper.apply(value);
+            return Objects.requireNonNull(r);
+        }
+    }
+
+    /**
      * If a value is present, returns an {@code Optional} describing the value,
      * otherwise returns an {@code Optional} produced by the supplying function.
      *
diff --git a/src/java.base/share/classes/java/util/OptionalDouble.java b/src/java.base/share/classes/java/util/OptionalDouble.java
--- a/src/java.base/share/classes/java/util/OptionalDouble.java
+++ b/src/java.base/share/classes/java/util/OptionalDouble.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,11 @@
 package java.util;
 
 import java.util.function.DoubleConsumer;
+import java.util.function.DoubleFunction;
 import java.util.function.DoubleSupplier;
+import java.util.function.DoubleToIntFunction;
+import java.util.function.DoubleToLongFunction;
+import java.util.function.DoubleUnaryOperator;
 import java.util.function.Supplier;
 import java.util.stream.DoubleStream;
 
@@ -185,6 +189,146 @@
     }
 
     /**
+     * If a value is present, returns an {@code OptionalDouble} describing the
+     * result of applying the given mapping function to the value, otherwise
+     * returns an empty {@code OptionalDouble}.
+     *
+     * @param mapper the mapping function to apply to a value, if present
+     * @return an {@code OptionalDouble} describing the result of applying a
+     *         mapping function to the value of this {@code OptionalDouble}, if
+     *         a value is present, otherwise an empty {@code OptionalDouble}
+     * @throws NullPointerException if the mapping function is {@code null}
+     * @since 13
+     */
+    public OptionalDouble map(DoubleUnaryOperator mapper) {
+        Objects.requireNonNull(mapper);
+        if (!isPresent()) {
+            return OptionalDouble.empty();
+        } else {
+            return OptionalDouble.of(mapper.applyAsDouble(value));
+        }
+    }
+
+    /**
+     * If a value is present, returns an {@code Optional} describing (as if by
+     * {@link Optional#ofNullable}) the result of applying the given mapping
+     * function to the value, otherwise returns an empty {@code Optional}.
+     *
+     * <p>If the mapping function returns a {@code null} result then this method
+     * returns an empty {@code Optional}.
+     *
+     * @param mapper the mapping function to apply to a value, if present
+     * @param <U> The type of the value returned from the mapping function
+     * @return an {@code Optional} describing the result of applying a mapping
+     *         function to the value of this {@code OptionalDouble}, if a value
+     *         is present, otherwise an empty {@code Optional}
+     * @throws NullPointerException if the mapping function is {@code null}
+     * @since 13
+     */
+    public <U> Optional<U> mapToObj(DoubleFunction<? extends U> mapper) {
+        Objects.requireNonNull(mapper);
+        if (!isPresent()) {
+            return Optional.empty();
+        } else {
+            return Optional.ofNullable(mapper.apply(value));
+        }
+    }
+
+    /**
+     * If a value is present, returns an {@code OptionalInt} describing the
+     * result of applying the given mapping function to the value, otherwise
+     * returns an empty {@code OptionalInt}.
+     *
+     * @param mapper the mapping function to apply to a value, if present
+     * @return an {@code OptionalInt} describing the result of applying a
+     *         mapping function to the value of this {@code OptionalDouble}, if
+     *         a value is present, otherwise an empty {@code OptionalInt}
+     * @throws NullPointerException if the mapping function is {@code null}
+     * @since 13
+     */
+    public OptionalInt mapToInt(DoubleToIntFunction mapper) {
+        Objects.requireNonNull(mapper);
+        if (!isPresent()) {
+            return OptionalInt.empty();
+        } else {
+            return OptionalInt.of(mapper.applyAsInt(value));
+        }
+    }
+
+    /**
+     * If a value is present, returns an {@code OptionalLong} describing the
+     * result of applying the given mapping function to the value, otherwise
+     * returns an empty {@code OptionalLong}.
+     *
+     * @param mapper the mapping function to apply to a value, if present
+     * @return an {@code OptionalLong} describing the result of applying a
+     *         mapping function to the value of this {@code OptionalDouble}, if
+     *         a value is present, otherwise an empty {@code OptionalLong}
+     * @throws NullPointerException if the mapping function is {@code null}
+     * @since 13
+     */
+    public OptionalLong mapToLong(DoubleToLongFunction mapper) {
+        Objects.requireNonNull(mapper);
+        if (!isPresent()) {
+            return OptionalLong.empty();
+        } else {
+            return OptionalLong.of(mapper.applyAsLong(value));
+        }
+    }
+
+    /**
+     * If a value is present, returns the result of applying the given
+     * {@code OptionalDouble}-bearing mapping function to the value, otherwise
+     * returns an empty {@code OptionalDouble}.
+     *
+     * <p>This method is similar to {@link #map(DoubleUnaryOperator)}, but the
+     * mapping function is one whose result is already an
+     * {@code OptionalDouble}, and if invoked, {@code flatMap} does not wrap it
+     * within an additional {@code OptionalDouble}.
+     *
+     * @param mapper the mapping function to apply to a value, if present
+     * @return the result of applying an {@code OptionalDouble}-bearing mapping
+     *         function to the value of this {@code OptionalDouble}, if a value
+     *         is present, otherwise an empty {@code OptionalDouble}
+     * @throws NullPointerException if the mapping function is {@code null} or
+     *         returns a {@code null} result
+     * @since 13
+     */
+    public OptionalDouble flatMap(DoubleFunction<? extends OptionalDouble> mapper) {
+        Objects.requireNonNull(mapper);
+        if (!isPresent()) {
+            return OptionalDouble.empty();
+        } else {
+            OptionalDouble r = mapper.apply(value);
+            return Objects.requireNonNull(r);
+        }
+    }
+
+    /**
+     * If a value is present, returns an {@code OptionalDouble} describing the
+     * value, otherwise returns an {@code OptionalDouble} produced by the supplying
+     * function.
+     *
+     * @param supplier the supplying function that produces an
+     *        {@code OptionalDouble} to be returned
+     * @return returns an {@code OptionalDouble} describing the value of this
+     *         {@code OptionalDouble}, if a value is present, otherwise an
+     *         {@code OptionalDouble} produced by the supplying function.
+     * @throws NullPointerException if the supplying function is {@code null} or
+     *         produces a {@code null} result
+     * @since 13
+     */
+    public OptionalDouble or(Supplier<? extends OptionalDouble> supplier) {
+        Objects.requireNonNull(supplier);
+        if (isPresent()) {
+            return this;
+        } else {
+            OptionalDouble r = supplier.get();
+            return Objects.requireNonNull(r);
+        }
+    }
+
+    /**
      * If a value is present, returns a sequential {@link DoubleStream}
      * containing only that value, otherwise returns an empty
      * {@code DoubleStream}.
diff --git a/src/java.base/share/classes/java/util/OptionalInt.java b/src/java.base/share/classes/java/util/OptionalInt.java
--- a/src/java.base/share/classes/java/util/OptionalInt.java
+++ b/src/java.base/share/classes/java/util/OptionalInt.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,11 @@
 package java.util;
 
 import java.util.function.IntConsumer;
+import java.util.function.IntFunction;
 import java.util.function.IntSupplier;
+import java.util.function.IntToDoubleFunction;
+import java.util.function.IntToLongFunction;
+import java.util.function.IntUnaryOperator;
 import java.util.function.Supplier;
 import java.util.stream.IntStream;
 
@@ -185,6 +189,146 @@
     }
 
     /**
+     * If a value is present, returns an {@code OptionalInt} describing the
+     * result of applying the given mapping function to the value, otherwise
+     * returns an empty {@code OptionalInt}.
+     *
+     * @param mapper the mapping function to apply to a value, if present
+     * @return an {@code OptionalInt} describing the result of applying a
+     *         mapping function to the value of this {@code OptionalInt}, if a
+     *         value is present, otherwise an empty {@code OptionalInt}
+     * @throws NullPointerException if the mapping function is {@code null}
+     * @since 13
+     */
+    public OptionalInt map(IntUnaryOperator mapper) {
+        Objects.requireNonNull(mapper);
+        if (!isPresent()) {
+            return OptionalInt.empty();
+        } else {
+            return OptionalInt.of(mapper.applyAsInt(value));
+        }
+    }
+
+    /**
+     * If a value is present, returns an {@code Optional} describing (as if by
+     * {@link Optional#ofNullable}) the result of applying the given mapping
+     * function to the value, otherwise returns an empty {@code Optional}.
+     *
+     * <p>If the mapping function returns a {@code null} result then this method
+     * returns an empty {@code Optional}.
+     *
+     * @param mapper the mapping function to apply to a value, if present
+     * @param <U> The type of the value returned from the mapping function
+     * @return an {@code Optional} describing the result of applying a mapping
+     *         function to the value of this {@code OptionalInt}, if a value is
+     *         present, otherwise an empty {@code Optional}
+     * @throws NullPointerException if the mapping function is {@code null}
+     * @since 13
+     */
+    public <U> Optional<U> mapToObj(IntFunction<? extends U> mapper) {
+        Objects.requireNonNull(mapper);
+        if (!isPresent()) {
+            return Optional.empty();
+        } else {
+            return Optional.ofNullable(mapper.apply(value));
+        }
+    }
+
+    /**
+     * If a value is present, returns an {@code OptionalLong} describing the
+     * result of applying the given mapping function to the value, otherwise
+     * returns an empty {@code OptionalLong}.
+     *
+     * @param mapper the mapping function to apply to a value, if present
+     * @return an {@code OptionalLong} describing the result of applying a
+     *         mapping function to the value of this {@code OptionalInt}, if a
+     *         value is present, otherwise an empty {@code OptionalLong}
+     * @throws NullPointerException if the mapping function is {@code null}
+     * @since 13
+     */
+    public OptionalLong mapToLong(IntToLongFunction mapper) {
+        Objects.requireNonNull(mapper);
+        if (!isPresent()) {
+            return OptionalLong.empty();
+        } else {
+            return OptionalLong.of(mapper.applyAsLong(value));
+        }
+    }
+
+    /**
+     * If a value is present, returns an {@code OptionalDouble} describing the
+     * result of applying the given mapping function to the value, otherwise
+     * returns an empty {@code OptionalDouble}.
+     *
+     * @param mapper the mapping function to apply to a value, if present
+     * @return an {@code OptionalDouble} describing the result of applying a
+     *         mapping function to the value of this {@code OptionalInt}, if a
+     *         value is present, otherwise an empty {@code OptionalDouble}
+     * @throws NullPointerException if the mapping function is {@code null}
+     * @since 13
+     */
+    public OptionalDouble mapToDouble(IntToDoubleFunction mapper) {
+        Objects.requireNonNull(mapper);
+        if (!isPresent()) {
+            return OptionalDouble.empty();
+        } else {
+            return OptionalDouble.of(mapper.applyAsDouble(value));
+        }
+    }
+
+    /**
+     * If a value is present, returns the result of applying the given
+     * {@code OptionalInt}-bearing mapping function to the value, otherwise
+     * returns an empty {@code OptionalInt}.
+     *
+     * <p>This method is similar to {@link #map(IntUnaryOperator)}, but the
+     * mapping function is one whose result is already an {@code OptionalInt},
+     * and if invoked, {@code flatMap} does not wrap it within an additional
+     * {@code OptionalInt}.
+     *
+     * @param mapper the mapping function to apply to a value, if present
+     * @return the result of applying an {@code OptionalInt}-bearing mapping
+     *         function to the value of this {@code OptionalInt}, if a value is
+     *         present, otherwise an empty {@code OptionalInt}
+     * @throws NullPointerException if the mapping function is {@code null} or
+     *         returns a {@code null} result
+     * @since 13
+     */
+    public OptionalInt flatMap(IntFunction<? extends OptionalInt> mapper) {
+        Objects.requireNonNull(mapper);
+        if (!isPresent()) {
+            return OptionalInt.empty();
+        } else {
+            OptionalInt r = mapper.apply(value);
+            return Objects.requireNonNull(r);
+        }
+    }
+
+    /**
+     * If a value is present, returns an {@code OptionalInt} describing the
+     * value, otherwise returns an {@code OptionalInt} produced by the supplying
+     * function.
+     *
+     * @param supplier the supplying function that produces an
+     *        {@code OptionalInt} to be returned
+     * @return returns an {@code OptionalInt} describing the value of this
+     *         {@code OptionalInt}, if a value is present, otherwise an
+     *         {@code OptionalInt} produced by the supplying function.
+     * @throws NullPointerException if the supplying function is {@code null} or
+     *         produces a {@code null} result
+     * @since 13
+     */
+    public OptionalInt or(Supplier<? extends OptionalInt> supplier) {
+        Objects.requireNonNull(supplier);
+        if (isPresent()) {
+            return this;
+        } else {
+            OptionalInt r = supplier.get();
+            return Objects.requireNonNull(r);
+        }
+    }
+
+    /**
      * If a value is present, returns a sequential {@link IntStream} containing
      * only that value, otherwise returns an empty {@code IntStream}.
      *
diff --git a/src/java.base/share/classes/java/util/OptionalLong.java b/src/java.base/share/classes/java/util/OptionalLong.java
--- a/src/java.base/share/classes/java/util/OptionalLong.java
+++ b/src/java.base/share/classes/java/util/OptionalLong.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,11 @@
 package java.util;
 
 import java.util.function.LongConsumer;
+import java.util.function.LongFunction;
 import java.util.function.LongSupplier;
+import java.util.function.LongToDoubleFunction;
+import java.util.function.LongToIntFunction;
+import java.util.function.LongUnaryOperator;
 import java.util.function.Supplier;
 import java.util.stream.LongStream;
 
@@ -185,6 +189,146 @@
     }
 
     /**
+     * If a value is present, returns an {@code OptionalLong} describing the
+     * result of applying the given mapping function to the value, otherwise
+     * returns an empty {@code OptionalLong}.
+     *
+     * @param mapper the mapping function to apply to a value, if present
+     * @return an {@code OptionalLong} describing the result of applying a
+     *         mapping function to the value of this {@code OptionalLong}, if a
+     *         value is present, otherwise an empty {@code OptionalLong}
+     * @throws NullPointerException if the mapping function is {@code null}
+     * @since 13
+     */
+    public OptionalLong map(LongUnaryOperator mapper) {
+        Objects.requireNonNull(mapper);
+        if (!isPresent()) {
+            return OptionalLong.empty();
+        } else {
+            return OptionalLong.of(mapper.applyAsLong(value));
+        }
+    }
+
+    /**
+     * If a value is present, returns an {@code Optional} describing (as if by
+     * {@link Optional#ofNullable}) the result of applying the given mapping
+     * function to the value, otherwise returns an empty {@code Optional}.
+     *
+     * <p>If the mapping function returns a {@code null} result then this method
+     * returns an empty {@code Optional}.
+     *
+     * @param mapper the mapping function to apply to a value, if present
+     * @param <U> The type of the value returned from the mapping function
+     * @return an {@code Optional} describing the result of applying a mapping
+     *         function to the value of this {@code OptionalLong}, if a value
+     *         is present, otherwise an empty {@code Optional}
+     * @throws NullPointerException if the mapping function is {@code null}
+     * @since 13
+     */
+    public <U> Optional<U> mapToObj(LongFunction<? extends U> mapper) {
+        Objects.requireNonNull(mapper);
+        if (!isPresent()) {
+            return Optional.empty();
+        } else {
+            return Optional.ofNullable(mapper.apply(value));
+        }
+    }
+
+    /**
+     * If a value is present, returns an {@code OptionalInt} describing the
+     * result of applying the given mapping function to the value, otherwise
+     * returns an empty {@code OptionalInt}.
+     *
+     * @param mapper the mapping function to apply to a value, if present
+     * @return an {@code OptionalInt} describing the result of applying a
+     *         mapping function to the value of this {@code OptionalLong}, if a
+     *         value is present, otherwise an empty {@code OptionalInt}
+     * @throws NullPointerException if the mapping function is {@code null}
+     * @since 13
+     */
+    public OptionalInt mapToInt(LongToIntFunction mapper) {
+        Objects.requireNonNull(mapper);
+        if (!isPresent()) {
+            return OptionalInt.empty();
+        } else {
+            return OptionalInt.of(mapper.applyAsInt(value));
+        }
+    }
+
+    /**
+     * If a value is present, returns an {@code OptionalDouble} describing the
+     * result of applying the given mapping function to the value, otherwise
+     * returns an empty {@code OptionalDouble}.
+     *
+     * @param mapper the mapping function to apply to a value, if present
+     * @return an {@code OptionalDouble} describing the result of applying a
+     *         mapping function to the value of this {@code OptionalLong}, if a
+     *         value is present, otherwise an empty {@code OptionalDouble}
+     * @throws NullPointerException if the mapping function is {@code null}
+     * @since 13
+     */
+    public OptionalDouble mapToDouble(LongToDoubleFunction mapper) {
+        Objects.requireNonNull(mapper);
+        if (!isPresent()) {
+            return OptionalDouble.empty();
+        } else {
+            return OptionalDouble.of(mapper.applyAsDouble(value));
+        }
+    }
+
+    /**
+     * If a value is present, returns the result of applying the given
+     * {@code OptionalLong}-bearing mapping function to the value, otherwise
+     * returns an empty {@code OptionalLong}.
+     *
+     * <p>This method is similar to {@link #map(LongUnaryOperator)}, but the
+     * mapping function is one whose result is already an {@code OptionalLong},
+     * and if invoked, {@code flatMap} does not wrap it within an additional
+     * {@code OptionalLong}.
+     *
+     * @param mapper the mapping function to apply to a value, if present
+     * @return the result of applying an {@code OptionalLong}-bearing mapping
+     *         function to the value of this {@code OptionalLong}, if a value is
+     *         present, otherwise an empty {@code OptionalLong}
+     * @throws NullPointerException if the mapping function is {@code null} or
+     *         returns a {@code null} result
+     * @since 13
+     */
+    public OptionalLong flatMap(LongFunction<? extends OptionalLong> mapper) {
+        Objects.requireNonNull(mapper);
+        if (!isPresent()) {
+            return OptionalLong.empty();
+        } else {
+            OptionalLong r = mapper.apply(value);
+            return Objects.requireNonNull(r);
+        }
+    }
+
+    /**
+     * If a value is present, returns an {@code OptionalLong} describing the
+     * value, otherwise returns an {@code OptionalLong} produced by the
+     * supplying function.
+     *
+     * @param supplier the supplying function that produces an
+     *        {@code OptionalLong} to be returned
+     * @return returns an {@code OptionalLong} describing the value of this
+     *         {@code OptionalLong}, if a value is present, otherwise an
+     *         {@code OptionalLong} produced by the supplying function.
+     * @throws NullPointerException if the supplying function is {@code null} or
+     *         produces a {@code null} result
+     * @since 13
+     */
+    public OptionalLong or(Supplier<? extends OptionalLong> supplier) {
+        Objects.requireNonNull(supplier);
+        if (isPresent()) {
+            return this;
+        } else {
+            OptionalLong r = supplier.get();
+            return Objects.requireNonNull(r);
+        }
+    }
+
+    /**
      * If a value is present, returns a sequential {@link LongStream} containing
      * only that value, otherwise returns an empty {@code LongStream}.
      *
diff --git a/test/jdk/java/util/Optional/Basic.java b/test/jdk/java/util/Optional/Basic.java
--- a/test/jdk/java/util/Optional/Basic.java
+++ b/test/jdk/java/util/Optional/Basic.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,9 @@
 import java.util.List;
 import java.util.NoSuchElementException;
 import java.util.Optional;
+import java.util.OptionalDouble;
+import java.util.OptionalInt;
+import java.util.OptionalLong;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import static java.util.stream.Collectors.toList;
@@ -44,7 +47,7 @@
     /**
      * Checks a block of assertions over an empty Optional.
      */
-    void checkEmpty(Optional<String> empty) {
+    static void checkEmpty(Optional<String> empty) {
         assertTrue(empty.equals(Optional.empty()));
         assertTrue(Optional.empty().equals(empty));
         assertFalse(empty.equals(Optional.of("unexpected")));
@@ -78,7 +81,7 @@
      * Checks a block of assertions over an Optional that is expected to
      * have a particular value present.
      */
-    void checkPresent(Optional<String> opt, String expected) {
+    static void checkPresent(Optional<String> opt, String expected) {
         assertFalse(opt.equals(Optional.empty()));
         assertFalse(Optional.empty().equals(opt));
         assertTrue(opt.equals(Optional.of(expected)));
@@ -161,6 +164,36 @@
     }
 
     @Test(groups = "unit")
+    public void testMapToIntEmpty() {
+        BasicInt.checkEmpty(Optional.empty().mapToInt(s -> { fail(); return 0; }));
+    }
+
+    @Test(groups = "unit")
+    public void testMapToIntPresent() {
+        BasicInt.checkPresent(Optional.of("xyzzy").mapToInt(s -> BasicInt.INTVAL), BasicInt.INTVAL);
+    }
+
+    @Test(groups = "unit")
+    public void testMapToLongEmpty() {
+        BasicLong.checkEmpty(Optional.empty().mapToLong(s -> { fail(); return 0L; }));
+    }
+
+    @Test(groups = "unit")
+    public void testMapToLongPresent() {
+        BasicLong.checkPresent(Optional.of("xyzzy").mapToLong(s -> BasicLong.LONGVAL), BasicLong.LONGVAL);
+    }
+
+    @Test(groups = "unit")
+    public void testMapToDoubleEmpty() {
+        BasicDouble.checkEmpty(Optional.empty().mapToDouble(s -> { fail(); return 0D; }));
+    }
+
+    @Test(groups = "unit")
+    public void testMapToDoublePresent() {
+        BasicDouble.checkPresent(Optional.of("xyzzy").mapToDouble(s -> BasicDouble.DOUBLEVAL), BasicDouble.DOUBLEVAL);
+    }
+
+    @Test(groups = "unit")
     public void testFlatMapEmpty() {
         checkEmpty(Optional.empty().flatMap(s -> { fail(); return Optional.of(""); }));
     }
@@ -179,6 +212,60 @@
     }
 
     @Test(groups = "unit")
+    public void testFlatMapToIntEmpty() {
+        BasicInt.checkEmpty(Optional.empty().flatMapToInt(s -> { fail(); return OptionalInt.of(0); }));
+    }
+
+    @Test(groups = "unit")
+    public void testFlatMapToIntPresentReturnEmpty() {
+        BasicInt.checkEmpty(Optional.of("xyzzy")
+                                    .flatMapToInt(s -> { assertEquals(s, "xyzzy"); return OptionalInt.empty(); }));
+    }
+
+    @Test(groups = "unit")
+    public void testFlatMapToIntPresentReturnPresent() {
+        BasicInt.checkPresent(Optional.of("xyzzy")
+                                      .flatMapToInt(s -> { assertEquals(s, "xyzzy"); return OptionalInt.of(BasicInt.INTVAL); }),
+                              BasicInt.INTVAL);
+    }
+
+    @Test(groups = "unit")
+    public void testFlatMapToLongEmpty() {
+        BasicLong.checkEmpty(Optional.empty().flatMapToLong(s -> { fail(); return OptionalLong.of(0L); }));
+    }
+
+    @Test(groups = "unit")
+    public void testFlatMapToLongPresentReturnEmpty() {
+        BasicLong.checkEmpty(Optional.of("xyzzy")
+                                     .flatMapToLong(s -> { assertEquals(s, "xyzzy"); return OptionalLong.empty(); }));
+    }
+
+    @Test(groups = "unit")
+    public void testFlatMapToLongPresentReturnPresent() {
+        BasicLong.checkPresent(Optional.of("xyzzy")
+                                       .flatMapToLong(s -> { assertEquals(s, "xyzzy"); return OptionalLong.of(BasicLong.LONGVAL); }),
+                               BasicLong.LONGVAL);
+    }
+
+    @Test(groups = "unit")
+    public void testFlatMapToDoubleEmpty() {
+        BasicDouble.checkEmpty(Optional.empty().flatMapToDouble(s -> { fail(); return OptionalDouble.of(0D); }));
+    }
+
+    @Test(groups = "unit")
+    public void testFlatMapToDoublePresentReturnEmpty() {
+        BasicDouble.checkEmpty(Optional.of("xyzzy")
+                                       .flatMapToDouble(s -> { assertEquals(s, "xyzzy"); return OptionalDouble.empty(); }));
+    }
+
+    @Test(groups = "unit")
+    public void testFlatMapToDoublePresentReturnPresent() {
+        BasicDouble.checkPresent(Optional.of("xyzzy")
+                                         .flatMapToDouble(s -> { assertEquals(s, "xyzzy"); return OptionalDouble.of(BasicDouble.DOUBLEVAL); }),
+                                 BasicDouble.DOUBLEVAL);
+    }
+
+    @Test(groups = "unit")
     public void testOrEmptyEmpty() {
         checkEmpty(Optional.<String>empty().or(() -> Optional.empty()));
     }
diff --git a/test/jdk/java/util/Optional/BasicDouble.java b/test/jdk/java/util/Optional/BasicDouble.java
--- a/test/jdk/java/util/Optional/BasicDouble.java
+++ b/test/jdk/java/util/Optional/BasicDouble.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -43,7 +43,7 @@
     /**
      * Checks a block of assertions over an empty OptionalDouble.
      */
-    void checkEmpty(OptionalDouble empty) {
+    static void checkEmpty(OptionalDouble empty) {
         assertTrue(empty.equals(OptionalDouble.empty()));
         assertTrue(OptionalDouble.empty().equals(empty));
         assertFalse(empty.equals(OptionalDouble.of(UNEXPECTED)));
@@ -77,7 +77,7 @@
      * Checks a block of assertions over an OptionalDouble that is expected to
      * have a particular value present.
      */
-    void checkPresent(OptionalDouble opt, double expected) {
+    static void checkPresent(OptionalDouble opt, double expected) {
         assertFalse(opt.equals(OptionalDouble.empty()));
         assertFalse(OptionalDouble.empty().equals(opt));
         assertTrue(opt.equals(OptionalDouble.of(expected)));
@@ -128,4 +128,77 @@
     public void testStreamPresent() {
         assertEquals(OptionalDouble.of(DOUBLEVAL).stream().toArray(), new double[] { DOUBLEVAL });
     }
+
+    @Test(groups = "unit")
+    public void testMapEmpty() {
+        checkEmpty(OptionalDouble.empty().map(s -> { fail(); return 0D; }));
+    }
+
+    @Test(groups = "unit")
+    public void testMapPresent() {
+        checkPresent(OptionalDouble.of(DOUBLEVAL).map(d -> d * 2), 2 * DOUBLEVAL);
+    }
+
+    @Test(groups = "unit")
+    public void testMapToObjEmpty() {
+        Basic.checkEmpty(OptionalDouble.empty().mapToObj(s -> { fail(); return ""; }));
+    }
+
+    @Test(groups = "unit")
+    public void testMapToObjPresent() {
+        Basic.checkPresent(OptionalDouble.of(DOUBLEVAL).mapToObj(d -> "plugh"), "plugh");
+    }
+
+    @Test(groups = "unit")
+    public void testMapToIntEmpty() {
+        BasicInt.checkEmpty(OptionalDouble.empty().mapToInt(s -> { fail(); return 0; }));
+    }
+
+    @Test(groups = "unit")
+    public void testMapToIntPresent() {
+        BasicInt.checkPresent(OptionalDouble.of(DOUBLEVAL).mapToInt(d -> BasicInt.INTVAL), BasicInt.INTVAL);
+    }
+
+    @Test(groups = "unit")
+    public void testMapToLongEmpty() {
+        BasicLong.checkEmpty(OptionalDouble.empty().mapToLong(s -> { fail(); return 0L; }));
+    }
+
+    @Test(groups = "unit")
+    public void testMapToLongPresent() {
+        BasicLong.checkPresent(OptionalDouble.of(DOUBLEVAL).mapToLong(d -> BasicLong.LONGVAL), BasicLong.LONGVAL);
+    }
+
+    @Test(groups = "unit")
+    public void testFlatMapEmpty() {
+        checkEmpty(OptionalDouble.empty().flatMap(s -> { fail(); return OptionalDouble.of(0D); }));
+    }
+
+    @Test(groups = "unit")
+    public void testFlatMapPresentReturnEmpty() {
+        checkEmpty(OptionalDouble.of(DOUBLEVAL)
+                                 .flatMap(d -> { assertEquals(d, DOUBLEVAL); return OptionalDouble.empty(); }));
+    }
+
+    @Test(groups = "unit")
+    public void testFlatMapPresentReturnPresent() {
+        checkPresent(OptionalDouble.of(DOUBLEVAL)
+                                   .flatMap(d -> { assertEquals(d, DOUBLEVAL); return OptionalDouble.of(Math.E); }),
+                     Math.E);
+    }
+
+    @Test(groups = "unit")
+    public void testOrEmptyEmpty() {
+        checkEmpty(OptionalDouble.empty().or(() -> OptionalDouble.empty()));
+    }
+
+    @Test(groups = "unit")
+    public void testOrEmptyPresent() {
+        checkPresent(OptionalDouble.empty().or(() -> OptionalDouble.of(DOUBLEVAL)), DOUBLEVAL);
+    }
+
+    @Test(groups = "unit")
+    public void testOrPresentDontCare() {
+        checkPresent(OptionalDouble.of(DOUBLEVAL).or(() -> { fail(); return OptionalDouble.of(0D); }), DOUBLEVAL);
+    }
 }
diff --git a/test/jdk/java/util/Optional/BasicInt.java b/test/jdk/java/util/Optional/BasicInt.java
--- a/test/jdk/java/util/Optional/BasicInt.java
+++ b/test/jdk/java/util/Optional/BasicInt.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,7 +44,7 @@
     /**
      * Checks a block of assertions over an empty OptionalInt.
      */
-    void checkEmpty(OptionalInt empty) {
+    static void checkEmpty(OptionalInt empty) {
         assertTrue(empty.equals(OptionalInt.empty()));
         assertTrue(OptionalInt.empty().equals(empty));
         assertFalse(empty.equals(OptionalInt.of(UNEXPECTED)));
@@ -78,7 +78,7 @@
      * Checks a block of assertions over an OptionalInt that is expected to
      * have a particular value present.
      */
-    void checkPresent(OptionalInt opt, int expected) {
+    static void checkPresent(OptionalInt opt, int expected) {
         assertFalse(opt.equals(OptionalInt.empty()));
         assertFalse(OptionalInt.empty().equals(opt));
         assertTrue(opt.equals(OptionalInt.of(expected)));
@@ -129,4 +129,77 @@
     public void testStreamPresent() {
         assertEquals(OptionalInt.of(INTVAL).stream().toArray(), new int[] { INTVAL });
     }
+
+    @Test(groups = "unit")
+    public void testMapEmpty() {
+        checkEmpty(OptionalInt.empty().map(s -> { fail(); return 0; }));
+    }
+
+    @Test(groups = "unit")
+    public void testMapPresent() {
+        checkPresent(OptionalInt.of(INTVAL).map(i -> i * 2), 2 * INTVAL);
+    }
+
+    @Test(groups = "unit")
+    public void testMapToObjEmpty() {
+        Basic.checkEmpty(OptionalInt.empty().mapToObj(s -> { fail(); return ""; }));
+    }
+
+    @Test(groups = "unit")
+    public void testMapToObjPresent() {
+        Basic.checkPresent(OptionalInt.of(INTVAL).mapToObj(i -> "plugh"), "plugh");
+    }
+
+    @Test(groups = "unit")
+    public void testMapToLongEmpty() {
+        BasicLong.checkEmpty(OptionalInt.empty().mapToLong(s -> { fail(); return 0L; }));
+    }
+
+    @Test(groups = "unit")
+    public void testMapToLongPresent() {
+        BasicLong.checkPresent(OptionalInt.of(INTVAL).mapToLong(i -> BasicLong.LONGVAL), BasicLong.LONGVAL);
+    }
+
+    @Test(groups = "unit")
+    public void testMapToDoubleEmpty() {
+        BasicDouble.checkEmpty(OptionalInt.empty().mapToDouble(s -> { fail(); return 0D; }));
+    }
+
+    @Test(groups = "unit")
+    public void testMapToDoublePresent() {
+        BasicDouble.checkPresent(OptionalInt.of(INTVAL).mapToDouble(i -> BasicDouble.DOUBLEVAL), BasicDouble.DOUBLEVAL);
+    }
+
+    @Test(groups = "unit")
+    public void testFlatMapEmpty() {
+        checkEmpty(OptionalInt.empty().flatMap(s -> { fail(); return OptionalInt.of(0); }));
+    }
+
+    @Test(groups = "unit")
+    public void testFlatMapPresentReturnEmpty() {
+        checkEmpty(OptionalInt.of(INTVAL)
+                              .flatMap(i -> { assertEquals(i, INTVAL); return OptionalInt.empty(); }));
+    }
+
+    @Test(groups = "unit")
+    public void testFlatMapPresentReturnPresent() {
+        checkPresent(OptionalInt.of(INTVAL)
+                                .flatMap(i -> { assertEquals(i, INTVAL); return OptionalInt.of(2 * INTVAL); }),
+                     2 * INTVAL);
+    }
+
+    @Test(groups = "unit")
+    public void testOrEmptyEmpty() {
+        checkEmpty(OptionalInt.empty().or(() -> OptionalInt.empty()));
+    }
+
+    @Test(groups = "unit")
+    public void testOrEmptyPresent() {
+        checkPresent(OptionalInt.empty().or(() -> OptionalInt.of(INTVAL)), INTVAL);
+    }
+
+    @Test(groups = "unit")
+    public void testOrPresentDontCare() {
+        checkPresent(OptionalInt.of(INTVAL).or(() -> { fail(); return OptionalInt.of(0); }), INTVAL);
+    }
 }
diff --git a/test/jdk/java/util/Optional/BasicLong.java b/test/jdk/java/util/Optional/BasicLong.java
--- a/test/jdk/java/util/Optional/BasicLong.java
+++ b/test/jdk/java/util/Optional/BasicLong.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -43,7 +43,7 @@
     /**
      * Checks a block of assertions over an empty OptionalLong.
      */
-    void checkEmpty(OptionalLong empty) {
+    static void checkEmpty(OptionalLong empty) {
         assertTrue(empty.equals(OptionalLong.empty()));
         assertTrue(OptionalLong.empty().equals(empty));
         assertFalse(empty.equals(OptionalLong.of(UNEXPECTED)));
@@ -77,7 +77,7 @@
      * Checks a block of assertions over an OptionalLong that is expected to
      * have a particular value present.
      */
-    void checkPresent(OptionalLong opt, long expected) {
+    static void checkPresent(OptionalLong opt, long expected) {
         assertFalse(opt.equals(OptionalLong.empty()));
         assertFalse(OptionalLong.empty().equals(opt));
         assertTrue(opt.equals(OptionalLong.of(expected)));
@@ -128,4 +128,77 @@
     public void testStreamPresent() {
         assertEquals(OptionalLong.of(LONGVAL).stream().toArray(), new long[] { LONGVAL });
     }
+
+    @Test(groups = "unit")
+    public void testMapEmpty() {
+        checkEmpty(OptionalLong.empty().map(s -> { fail(); return 0L; }));
+    }
+
+    @Test(groups = "unit")
+    public void testMapPresent() {
+        checkPresent(OptionalLong.of(LONGVAL).map(l -> l * 2), 2 * LONGVAL);
+    }
+
+    @Test(groups = "unit")
+    public void testMapToObjEmpty() {
+        Basic.checkEmpty(OptionalLong.empty().mapToObj(s -> { fail(); return ""; }));
+    }
+
+    @Test(groups = "unit")
+    public void testMapToObjPresent() {
+        Basic.checkPresent(OptionalLong.of(LONGVAL).mapToObj(l -> "plugh"), "plugh");
+    }
+
+    @Test(groups = "unit")
+    public void testMapToIntEmpty() {
+        BasicInt.checkEmpty(OptionalLong.empty().mapToInt(s -> { fail(); return 0; }));
+    }
+
+    @Test(groups = "unit")
+    public void testMapToIntPresent() {
+        BasicInt.checkPresent(OptionalLong.of(LONGVAL).mapToInt(l -> BasicInt.INTVAL), BasicInt.INTVAL);
+    }
+
+    @Test(groups = "unit")
+    public void testMapToDoubleEmpty() {
+        BasicDouble.checkEmpty(OptionalLong.empty().mapToDouble(s -> { fail(); return 0D; }));
+    }
+
+    @Test(groups = "unit")
+    public void testMapToDoublePresent() {
+        BasicDouble.checkPresent(OptionalLong.of(LONGVAL).mapToDouble(l -> BasicDouble.DOUBLEVAL), BasicDouble.DOUBLEVAL);
+    }
+
+    @Test(groups = "unit")
+    public void testFlatMapEmpty() {
+        checkEmpty(OptionalLong.empty().flatMap(s -> { fail(); return OptionalLong.of(0L); }));
+    }
+
+    @Test(groups = "unit")
+    public void testFlatMapPresentReturnEmpty() {
+        checkEmpty(OptionalLong.of(LONGVAL)
+                              .flatMap(d -> { assertEquals(d, LONGVAL); return OptionalLong.empty(); }));
+    }
+
+    @Test(groups = "unit")
+    public void testFlatMapPresentReturnPresent() {
+        checkPresent(OptionalLong.of(LONGVAL)
+                                 .flatMap(d -> { assertEquals(d, LONGVAL); return OptionalLong.of(2 * LONGVAL); }),
+                     2 * LONGVAL);
+    }
+
+    @Test(groups = "unit")
+    public void testOrEmptyEmpty() {
+        checkEmpty(OptionalLong.empty().or(() -> OptionalLong.empty()));
+    }
+
+    @Test(groups = "unit")
+    public void testOrEmptyPresent() {
+        checkPresent(OptionalLong.empty().or(() -> OptionalLong.of(LONGVAL)), LONGVAL);
+    }
+
+    @Test(groups = "unit")
+    public void testOrPresentDontCare() {
+        checkPresent(OptionalLong.of(LONGVAL).or(() -> { fail(); return OptionalLong.of(0L); }), LONGVAL);
+    }
 }


More information about the core-libs-dev mailing list