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