1 /*
  2  * Copyright (c) 2012, 2020, 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.IntConsumer;
 28 import java.util.function.IntSupplier;
 29 import java.util.function.Supplier;
 30 import java.util.stream.IntStream;
 31 
 32 /**
 33  * A container object which may or may not contain an {@code int} value.
 34  * If a value is present, {@code isPresent()} returns {@code true}. If no
 35  * value is present, the object is considered <i>empty</i> and
 36  * {@code isPresent()} returns {@code false}.
 37  *
 38  * <p>Additional methods that depend on the presence or absence of a contained
 39  * value are provided, such as {@link #orElse(int) orElse()}
 40  * (returns a default value if no value is present) and
 41  * {@link #ifPresent(IntConsumer) ifPresent()} (performs an
 42  * action if a value is present).
 43  *
 44  * <p>This is a <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>
 45  * class; programmers should treat instances that are {@linkplain #equals(Object) equal}
 46  * as interchangeable and should not use instances for synchronization, mutexes, or
 47  * with {@linkplain java.lang.ref.Reference object references}.
 48  *
 49  * <div class="preview-block">
 50  *      <div class="preview-comment">
 51  *          When preview features are enabled, {@code OptionalInt} is a {@linkplain Class#isValue value class}.
 52  *          Use of value class instances for synchronization, mutexes, or with
 53  *          {@linkplain java.lang.ref.Reference object references} result in
 54  *          {@link IdentityException}.
 55  *      </div>
 56  * </div>
 57  *
 58  * @apiNote
 59  * {@code OptionalInt} is primarily intended for use as a method return type where
 60  * there is a clear need to represent "no result." A variable whose type is
 61  * {@code OptionalInt} should never itself be {@code null}; it should always point
 62  * to an {@code OptionalInt} instance.
 63  *
 64  * @since 1.8
 65  */
 66 @jdk.internal.ValueBased
 67 public final /*value*/ class OptionalInt {
 68     /**
 69      * Common instance for {@code empty()}.
 70      */
 71     private static final OptionalInt EMPTY = new OptionalInt();
 72 
 73     /**
 74      * If true then the value is present, otherwise indicates no value is present
 75      */
 76     private final boolean isPresent;
 77     private final int value;
 78 
 79     /**
 80      * Construct an empty instance.
 81      *
 82      * @implNote Generally only one empty instance, {@link OptionalInt#EMPTY},
 83      * should exist per VM.
 84      */
 85     private OptionalInt() {
 86         this.isPresent = false;
 87         this.value = 0;
 88     }
 89 
 90     /**
 91      * Returns an empty {@code OptionalInt} instance.  No value is present for
 92      * this {@code OptionalInt}.
 93      *
 94      * @apiNote
 95      * Though it may be tempting to do so, avoid testing if an object is empty
 96      * by comparing with {@code ==} or {@code !=} against instances returned by
 97      * {@code OptionalInt.empty()}.  There is no guarantee that it is a singleton.
 98      * Instead, use {@link #isEmpty()} or {@link #isPresent()}.
 99      *
100      * @return an empty {@code OptionalInt}
101      */
102     public static OptionalInt empty() {
103         return EMPTY;
104     }
105 
106     /**
107      * Construct an instance with the described value.
108      *
109      * @param value the int value to describe
110      */
111     private OptionalInt(int value) {
112         this.isPresent = true;
113         this.value = value;
114     }
115 
116     /**
117      * Returns an {@code OptionalInt} describing the given value.
118      *
119      * @param value the value to describe
120      * @return an {@code OptionalInt} with the value present
121      */
122     public static OptionalInt of(int value) {
123         return new OptionalInt(value);
124     }
125 
126     /**
127      * If a value is present, returns the value, otherwise throws
128      * {@code NoSuchElementException}.
129      *
130      * @apiNote
131      * The preferred alternative to this method is {@link #orElseThrow()}.
132      *
133      * @return the value described by this {@code OptionalInt}
134      * @throws NoSuchElementException if no value is present
135      */
136     public int getAsInt() {
137         if (!isPresent) {
138             throw new NoSuchElementException("No value present");
139         }
140         return value;
141     }
142 
143     /**
144      * If a value is present, returns {@code true}, otherwise {@code false}.
145      *
146      * @return {@code true} if a value is present, otherwise {@code false}
147      */
148     public boolean isPresent() {
149         return isPresent;
150     }
151 
152     /**
153      * If a value is not present, returns {@code true}, otherwise
154      * {@code false}.
155      *
156      * @return  {@code true} if a value is not present, otherwise {@code false}
157      * @since   11
158      */
159     public boolean isEmpty() {
160         return !isPresent;
161     }
162 
163     /**
164      * If a value is present, performs the given action with the value,
165      * otherwise does nothing.
166      *
167      * @param action the action to be performed, if a value is present
168      * @throws NullPointerException if value is present and the given action is
169      *         {@code null}
170      */
171     public void ifPresent(IntConsumer action) {
172         if (isPresent) {
173             action.accept(value);
174         }
175     }
176 
177     /**
178      * If a value is present, performs the given action with the value,
179      * otherwise performs the given empty-based action.
180      *
181      * @param action the action to be performed, if a value is present
182      * @param emptyAction the empty-based action to be performed, if no value is
183      *        present
184      * @throws NullPointerException if a value is present and the given action
185      *         is {@code null}, or no value is present and the given empty-based
186      *         action is {@code null}.
187      * @since 9
188      */
189     public void ifPresentOrElse(IntConsumer action, Runnable emptyAction) {
190         if (isPresent) {
191             action.accept(value);
192         } else {
193             emptyAction.run();
194         }
195     }
196 
197     /**
198      * If a value is present, returns a sequential {@link IntStream} containing
199      * only that value, otherwise returns an empty {@code IntStream}.
200      *
201      * @apiNote
202      * This method can be used to transform a {@code Stream} of optional
203      * integers to an {@code IntStream} of present integers:
204      * <pre>{@code
205      *     Stream<OptionalInt> os = ..
206      *     IntStream s = os.flatMapToInt(OptionalInt::stream)
207      * }</pre>
208      *
209      * @return the optional value as an {@code IntStream}
210      * @since 9
211      */
212     public IntStream stream() {
213         if (isPresent) {
214             return IntStream.of(value);
215         } else {
216             return IntStream.empty();
217         }
218     }
219 
220     /**
221      * If a value is present, returns the value, otherwise returns
222      * {@code other}.
223      *
224      * @param other the value to be returned, if no value is present
225      * @return the value, if present, otherwise {@code other}
226      */
227     public int orElse(int other) {
228         return isPresent ? value : other;
229     }
230 
231     /**
232      * If a value is present, returns the value, otherwise returns the result
233      * produced by the supplying function.
234      *
235      * @param supplier the supplying function that produces a value to be returned
236      * @return the value, if present, otherwise the result produced by the
237      *         supplying function
238      * @throws NullPointerException if no value is present and the supplying
239      *         function is {@code null}
240      */
241     public int orElseGet(IntSupplier supplier) {
242         return isPresent ? value : supplier.getAsInt();
243     }
244 
245     /**
246      * If a value is present, returns the value, otherwise throws
247      * {@code NoSuchElementException}.
248      *
249      * @return the value described by this {@code OptionalInt}
250      * @throws NoSuchElementException if no value is present
251      * @since 10
252      */
253     public int orElseThrow() {
254         if (!isPresent) {
255             throw new NoSuchElementException("No value present");
256         }
257         return value;
258     }
259 
260     /**
261      * If a value is present, returns the value, otherwise throws an exception
262      * produced by the exception supplying function.
263      *
264      * @apiNote
265      * A method reference to the exception constructor with an empty argument
266      * list can be used as the supplier. For example,
267      * {@code IllegalStateException::new}
268      *
269      * @param <X> Type of the exception to be thrown
270      * @param exceptionSupplier the supplying function that produces an
271      *        exception to be thrown
272      * @return the value, if present
273      * @throws X if no value is present
274      * @throws NullPointerException if no value is present and the exception
275      *         supplying function is {@code null}
276      */
277     public<X extends Throwable> int orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
278         if (isPresent) {
279             return value;
280         } else {
281             throw exceptionSupplier.get();
282         }
283     }
284 
285     /**
286      * Indicates whether some other object is "equal to" this
287      * {@code OptionalInt}.  The other object is considered equal if:
288      * <ul>
289      * <li>it is also an {@code OptionalInt} and;
290      * <li>both instances have no value present or;
291      * <li>the present values are "equal to" each other via {@code ==}.
292      * </ul>
293      *
294      * @param obj an object to be tested for equality
295      * @return {@code true} if the other object is "equal to" this object
296      *         otherwise {@code false}
297      */
298     @Override
299     public boolean equals(Object obj) {
300         if (this == obj) {
301             return true;
302         }
303 
304         return obj instanceof OptionalInt other
305                 && (isPresent && other.isPresent
306                 ? value == other.value
307                 : isPresent == other.isPresent);
308     }
309 
310     /**
311      * Returns the hash code of the value, if present, otherwise {@code 0}
312      * (zero) if no value is present.
313      *
314      * @return hash code value of the present value or {@code 0} if no value is
315      *         present
316      */
317     @Override
318     public int hashCode() {
319         return isPresent ? Integer.hashCode(value) : 0;
320     }
321 
322     /**
323      * Returns a non-empty string representation of this {@code OptionalInt}
324      * suitable for debugging.  The exact presentation format is unspecified and
325      * may vary between implementations and versions.
326      *
327      * @implSpec
328      * If a value is present the result must include its string representation
329      * in the result.  Empty and present {@code OptionalInt}s must be
330      * unambiguously differentiable.
331      *
332      * @return the string representation of this instance
333      */
334     @Override
335     public String toString() {
336         return isPresent
337                 ? ("OptionalInt[" + value + "]")
338                 : "OptionalInt.empty";
339     }
340 }
--- EOF ---