src/java.base/share/classes/java/util/OptionalDouble.java
changeset 47216 71c04702a3d5
parent 44779 2a39971d67ab
child 48328 7acf5700d542
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 package java.util;
       
    26 
       
    27 import java.util.function.DoubleConsumer;
       
    28 import java.util.function.DoubleSupplier;
       
    29 import java.util.function.Supplier;
       
    30 import java.util.stream.DoubleStream;
       
    31 
       
    32 /**
       
    33  * A container object which may or may not contain a {@code double} value.  If a
       
    34  * value is present, {@code isPresent()} returns {@code true} and
       
    35  * {@code getAsDouble()} returns the value.
       
    36  *
       
    37  * <p>Additional methods that depend on the presence or absence of a contained
       
    38  * value are provided, such as {@link #orElse(double) orElse()}
       
    39  * (returns a default value if no value is present) and
       
    40  * {@link #ifPresent(DoubleConsumer) ifPresent()} (performs
       
    41  * an action if a value is present).
       
    42  *
       
    43  * <p>This is a <a href="../lang/doc-files/ValueBased.html">value-based</a>
       
    44  * class; use of identity-sensitive operations (including reference equality
       
    45  * ({@code ==}), identity hash code, or synchronization) on instances of
       
    46  * {@code OptionalDouble} may have unpredictable results and should be avoided.
       
    47  *
       
    48  * @apiNote
       
    49  * {@code OptionalDouble} is primarily intended for use as a method return type where
       
    50  * there is a clear need to represent "no result." A variable whose type is
       
    51  * {@code OptionalDouble} should never itself be {@code null}; it should always point
       
    52  * to an {@code OptionalDouble} instance.
       
    53  *
       
    54  * @since 1.8
       
    55  */
       
    56 public final class OptionalDouble {
       
    57     /**
       
    58      * Common instance for {@code empty()}.
       
    59      */
       
    60     private static final OptionalDouble EMPTY = new OptionalDouble();
       
    61 
       
    62     /**
       
    63      * If true then the value is present, otherwise indicates no value is present
       
    64      */
       
    65     private final boolean isPresent;
       
    66     private final double value;
       
    67 
       
    68     /**
       
    69      * Construct an empty instance.
       
    70      *
       
    71      * @implNote generally only one empty instance, {@link OptionalDouble#EMPTY},
       
    72      * should exist per VM.
       
    73      */
       
    74     private OptionalDouble() {
       
    75         this.isPresent = false;
       
    76         this.value = Double.NaN;
       
    77     }
       
    78 
       
    79     /**
       
    80      * Returns an empty {@code OptionalDouble} instance.  No value is present
       
    81      * for this {@code OptionalDouble}.
       
    82      *
       
    83      * @apiNote
       
    84      * Though it may be tempting to do so, avoid testing if an object is empty
       
    85      * by comparing with {@code ==} against instances returned by
       
    86      * {@code OptionalDouble.empty()}.  There is no guarantee that it is a singleton.
       
    87      * Instead, use {@link #isPresent()}.
       
    88      *
       
    89      *  @return an empty {@code OptionalDouble}.
       
    90      */
       
    91     public static OptionalDouble empty() {
       
    92         return EMPTY;
       
    93     }
       
    94 
       
    95     /**
       
    96      * Construct an instance with the described value.
       
    97      *
       
    98      * @param value the double value to describe.
       
    99      */
       
   100     private OptionalDouble(double value) {
       
   101         this.isPresent = true;
       
   102         this.value = value;
       
   103     }
       
   104 
       
   105     /**
       
   106      * Returns an {@code OptionalDouble} describing the given value.
       
   107      *
       
   108      * @param value the value to describe
       
   109      * @return an {@code OptionalDouble} with the value present
       
   110      */
       
   111     public static OptionalDouble of(double value) {
       
   112         return new OptionalDouble(value);
       
   113     }
       
   114 
       
   115     /**
       
   116      * If a value is present, returns the value, otherwise throws
       
   117      * {@code NoSuchElementException}.
       
   118      *
       
   119      * @apiNote
       
   120      * The methods {@link #orElse(double) orElse} and
       
   121      * {@link #orElseGet(DoubleSupplier) orElseGet}
       
   122      * are generally preferable to this method, as they return a substitute
       
   123      * value if the value is absent, instead of throwing an exception.
       
   124      *
       
   125      * @return the value described by this {@code OptionalDouble}
       
   126      * @throws NoSuchElementException if no value is present
       
   127      * @see OptionalDouble#isPresent()
       
   128      */
       
   129     public double getAsDouble() {
       
   130         if (!isPresent) {
       
   131             throw new NoSuchElementException("No value present");
       
   132         }
       
   133         return value;
       
   134     }
       
   135 
       
   136     /**
       
   137      * If a value is present, returns {@code true}, otherwise {@code false}.
       
   138      *
       
   139      * @return {@code true} if a value is present, otherwise {@code false}
       
   140      */
       
   141     public boolean isPresent() {
       
   142         return isPresent;
       
   143     }
       
   144 
       
   145     /**
       
   146      * If a value is present, performs the given action with the value,
       
   147      * otherwise does nothing.
       
   148      *
       
   149      * @param action the action to be performed, if a value is present
       
   150      * @throws NullPointerException if value is present and the given action is
       
   151      *         {@code null}
       
   152      */
       
   153     public void ifPresent(DoubleConsumer action) {
       
   154         if (isPresent) {
       
   155             action.accept(value);
       
   156         }
       
   157     }
       
   158 
       
   159     /**
       
   160      * If a value is present, performs the given action with the value,
       
   161      * otherwise performs the given empty-based action.
       
   162      *
       
   163      * @param action the action to be performed, if a value is present
       
   164      * @param emptyAction the empty-based action to be performed, if no value is
       
   165      * present
       
   166      * @throws NullPointerException if a value is present and the given action
       
   167      *         is {@code null}, or no value is present and the given empty-based
       
   168      *         action is {@code null}.
       
   169      * @since 9
       
   170      */
       
   171     public void ifPresentOrElse(DoubleConsumer action, Runnable emptyAction) {
       
   172         if (isPresent) {
       
   173             action.accept(value);
       
   174         } else {
       
   175             emptyAction.run();
       
   176         }
       
   177     }
       
   178 
       
   179     /**
       
   180      * If a value is present, returns a sequential {@link DoubleStream}
       
   181      * containing only that value, otherwise returns an empty
       
   182      * {@code DoubleStream}.
       
   183      *
       
   184      * @apiNote
       
   185      * This method can be used to transform a {@code Stream} of optional doubles
       
   186      * to a {@code DoubleStream} of present doubles:
       
   187      * <pre>{@code
       
   188      *     Stream<OptionalDouble> os = ..
       
   189      *     DoubleStream s = os.flatMapToDouble(OptionalDouble::stream)
       
   190      * }</pre>
       
   191      *
       
   192      * @return the optional value as a {@code DoubleStream}
       
   193      * @since 9
       
   194      */
       
   195     public DoubleStream stream() {
       
   196         if (isPresent) {
       
   197             return DoubleStream.of(value);
       
   198         } else {
       
   199             return DoubleStream.empty();
       
   200         }
       
   201     }
       
   202 
       
   203     /**
       
   204      * If a value is present, returns the value, otherwise returns
       
   205      * {@code other}.
       
   206      *
       
   207      * @param other the value to be returned, if no value is present
       
   208      * @return the value, if present, otherwise {@code other}
       
   209      */
       
   210     public double orElse(double other) {
       
   211         return isPresent ? value : other;
       
   212     }
       
   213 
       
   214     /**
       
   215      * If a value is present, returns the value, otherwise returns the result
       
   216      * produced by the supplying function.
       
   217      *
       
   218      * @param supplier the supplying function that produces a value to be returned
       
   219      * @return the value, if present, otherwise the result produced by the
       
   220      *         supplying function
       
   221      * @throws NullPointerException if no value is present and the supplying
       
   222      *         function is {@code null}
       
   223      */
       
   224     public double orElseGet(DoubleSupplier supplier) {
       
   225         return isPresent ? value : supplier.getAsDouble();
       
   226     }
       
   227 
       
   228     /**
       
   229      * If a value is present, returns the value, otherwise throws an exception
       
   230      * produced by the exception supplying function.
       
   231      *
       
   232      * @apiNote
       
   233      * A method reference to the exception constructor with an empty argument
       
   234      * list can be used as the supplier. For example,
       
   235      * {@code IllegalStateException::new}
       
   236      *
       
   237      * @param <X> Type of the exception to be thrown
       
   238      * @param exceptionSupplier the supplying function that produces an
       
   239      *        exception to be thrown
       
   240      * @return the value, if present
       
   241      * @throws X if no value is present
       
   242      * @throws NullPointerException if no value is present and the exception
       
   243      *         supplying function is {@code null}
       
   244      */
       
   245     public<X extends Throwable> double orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
       
   246         if (isPresent) {
       
   247             return value;
       
   248         } else {
       
   249             throw exceptionSupplier.get();
       
   250         }
       
   251     }
       
   252 
       
   253     /**
       
   254      * Indicates whether some other object is "equal to" this
       
   255      * {@code OptionalDouble}. The other object is considered equal if:
       
   256      * <ul>
       
   257      * <li>it is also an {@code OptionalDouble} and;
       
   258      * <li>both instances have no value present or;
       
   259      * <li>the present values are "equal to" each other via
       
   260      * {@code Double.compare() == 0}.
       
   261      * </ul>
       
   262      *
       
   263      * @param obj an object to be tested for equality
       
   264      * @return {@code true} if the other object is "equal to" this object
       
   265      *         otherwise {@code false}
       
   266      */
       
   267     @Override
       
   268     public boolean equals(Object obj) {
       
   269         if (this == obj) {
       
   270             return true;
       
   271         }
       
   272 
       
   273         if (!(obj instanceof OptionalDouble)) {
       
   274             return false;
       
   275         }
       
   276 
       
   277         OptionalDouble other = (OptionalDouble) obj;
       
   278         return (isPresent && other.isPresent)
       
   279                ? Double.compare(value, other.value) == 0
       
   280                : isPresent == other.isPresent;
       
   281     }
       
   282 
       
   283     /**
       
   284      * Returns the hash code of the value, if present, otherwise {@code 0}
       
   285      * (zero) if no value is present.
       
   286      *
       
   287      * @return hash code value of the present value or {@code 0} if no value is
       
   288      *         present
       
   289      */
       
   290     @Override
       
   291     public int hashCode() {
       
   292         return isPresent ? Double.hashCode(value) : 0;
       
   293     }
       
   294 
       
   295     /**
       
   296      * Returns a non-empty string representation of this {@code OptionalDouble}
       
   297      * suitable for debugging.  The exact presentation format is unspecified and
       
   298      * may vary between implementations and versions.
       
   299      *
       
   300      * @implSpec
       
   301      * If a value is present the result must include its string representation
       
   302      * in the result.  Empty and present {@code OptionalDouble}s must be
       
   303      * unambiguously differentiable.
       
   304      *
       
   305      * @return the string representation of this instance
       
   306      */
       
   307     @Override
       
   308     public String toString() {
       
   309         return isPresent
       
   310                 ? String.format("OptionalDouble[%s]", value)
       
   311                 : "OptionalDouble.empty";
       
   312     }
       
   313 }