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