1 /*
   2  * Copyright (c) 2012, 2013, 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 
  31 /**
  32  * A container object which may or may not contain a {@code double} value.
  33  * If a value is present, {@code isPresent()} will return {@code true} and
  34  * {@code get()} will return the value.
  35  *
  36  * <p>Additional methods that depend on the presence or absence of a contained
  37  * value are provided, such as {@link #orElse(java.lang.Object) orElse()}
  38  * (return a default value if value not present) and
  39  * {@link #ifPresent(java.util.function.Consumer) ifPresent()} (execute a block
  40  * of code if the value is present.)
  41  *
  42  * @since 1.8
  43  */
  44 public final class OptionalDouble {
  45     /**
  46      * Common instance for {@code empty()}.
  47      */
  48     private final static OptionalDouble EMPTY = new OptionalDouble();
  49 
  50     /**
  51      * If true then the value is present, otherwise indicates no value is present
  52      */
  53     private final boolean isPresent;
  54     private final double value;
  55 
  56     /**
  57      * Construct a non-empty instance
  58      *
  59      * @param value the double value to be present.
  60      */
  61     private OptionalDouble(double value) {
  62         this.isPresent = true;
  63         this.value = value;
  64     }
  65 
  66     /**
  67      * Construct an empty instance.
  68      *
  69      * @implNote generally only one empty instance, {@link OptionalDouble#EMPTY},
  70      * should exist per VM.
  71      */
  72     private OptionalDouble() {
  73         this.isPresent = false;
  74         this.value = Double.NaN;
  75     }
  76 
  77     /**
  78      * Return an empty {@code OptionalDouble}.  No value is present for this Optional.
  79      *
  80      * @apiNote Though it may be tempting to do so, avoid testing if an object
  81      * is empty by comparing with {@code ==} against instances returned
  82      * {@code Option.empty()}. There is no guarantee that it is a singleton.
  83      * Instead, use {@code isPresent()}.
  84      *
  85      *  @return an empty {@code OptionalDouble}.
  86      */
  87     @SuppressWarnings("unchecked")
  88     public static OptionalDouble empty() {
  89         return EMPTY;
  90     }
  91 
  92     /**
  93      * Create a new {@code OptionalDouble} with a present value
  94      * @param value The double value
  95      * @param value new {@code OptionalDouble} with a present value.
  96      */
  97     public static OptionalDouble of(double value) {
  98         return new OptionalDouble(value);
  99     }
 100 
 101     /**
 102      * If a value is present in this {@code OptionalDouble}, returns the value,
 103      * otherwise throws {@code NoSuchElementException}.
 104      *
 105      * @return the value held by this {@code OptionalDouble}.
 106      * @throws NoSuchElementException if there is no value present.
 107      *
 108      * @see OptionalDouble#isPresent()
 109      */
 110     public double getAsDouble() {
 111         if (!isPresent) {
 112             throw new NoSuchElementException("No value present");
 113         }
 114         return value;
 115     }
 116 
 117     /**
 118      * Return {@code true} if there is a value present, otherwise {@code false}.
 119      *
 120      * @return {@code true} if there is a value present, otherwise {@code false}.
 121      */
 122     public boolean isPresent() {
 123         return isPresent;
 124     }
 125 
 126     /**
 127      * Execute the specified consumer with the value if a value is present,
 128      * otherwise do nothing.
 129      *
 130      * @param consumer block to be executed if a value is present.
 131      * @throws NullPointerException if value is present and {@code consumer} is
 132      * null.
 133      */
 134     public void ifPresent(DoubleConsumer consumer) {
 135         if (isPresent)
 136             consumer.accept(value);
 137     }
 138 
 139     /**
 140      * Return the value if present, otherwise return {@code other}.
 141      *
 142      * @param other value to be returned if there is no value present.
 143      * @return the value, if present, otherwise {@code other}.
 144      */
 145     public double orElse(double other) {
 146         return isPresent ? value : other;
 147     }
 148 
 149     /**
 150      * Return the value if present, otherwise invoke {@code other} and return
 151      * the result of that invocation.
 152      *
 153      * @param other {@code DoubleSupplier} who's result is returned if there is no
 154      * value present.
 155      * @return the value if present otherwise return result of {@code other}.
 156      * @throws NullPointerException if value is absent and {@code other} is null.
 157      */
 158     public double orElseGet(DoubleSupplier other) {
 159         return isPresent ? value : other.getAsDouble();
 160     }
 161 
 162     /**
 163      * Return the contained value, if present, otherwise throw an exception
 164      * to be created by the provided supplier.
 165      *
 166      * @param <V> Type of the exception to be thrown.
 167      * @param exceptionSupplier The supplier which will return the exception to
 168      * be thrown.
 169      * @return the value.
 170      * @throws V if there is no value present.
 171      * @throws NullPointerException if value is absent and
 172      * {@code exceptionSupplier} is null.
 173      */
 174     public<V extends Throwable> double orElseThrow(Supplier<V> exceptionSupplier) throws V {
 175         if (isPresent) {
 176             return value;
 177         } else {
 178             throw exceptionSupplier.get();
 179         }
 180     }
 181 
 182     @Override
 183     public boolean equals(Object o) {
 184         if (this == o) {
 185             return true;
 186         }
 187 
 188         if (!(o instanceof OptionalDouble)) {
 189             return false;
 190         }
 191 
 192         OptionalDouble other = (OptionalDouble) o;
 193         return (isPresent && other.isPresent)
 194                ? Double.compare(value, other.value) == 0
 195                : isPresent == other.isPresent;
 196     }
 197 
 198     @Override
 199     public int hashCode() {
 200         return Double.hashCode(value);
 201     }
 202 
 203     @Override
 204     public String toString() {
 205         return isPresent
 206                         ? String.format("DoubleOptional[%s]", value)
 207                         : "DoubleOptional.empty";
 208     }
 209 }