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