Created
October 17, 2021 06:37
-
-
Save KamilaBorowska/34b8c8717191c191e577a843cfc9e15b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. | |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
* | |
* This code is free software; you can redistribute it and/or modify it | |
* under the terms of the GNU General Public License version 2 only, as | |
* published by the Free Software Foundation. Oracle designates this | |
* particular file as subject to the "Classpath" exception as provided | |
* by Oracle in the LICENSE file that accompanied this code. | |
* | |
* This code is distributed in the hope that it will be useful, but WITHOUT | |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
* version 2 for more details (a copy is included in the LICENSE file that | |
* accompanied this code). | |
* | |
* You should have received a copy of the GNU General Public License version | |
* 2 along with this work; if not, write to the Free Software Foundation, | |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
* | |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
* or visit www.oracle.com if you need additional information or have any | |
* questions. | |
*/ | |
package pw.xfix; | |
import java.util.NoSuchElementException; | |
import java.util.function.LongConsumer; | |
import java.util.function.LongSupplier; | |
import java.util.function.Supplier; | |
import java.util.stream.LongStream; | |
/** | |
* A container object which may or may not contain a {@code long} value. | |
* If a value is present, {@code isPresent()} returns {@code true}. If no | |
* value is present, the object is considered <i>empty</i> and | |
* {@code isPresent()} returns {@code false}. | |
* | |
* <p>Additional methods that depend on the presence or absence of a contained | |
* value are provided, such as {@link #orElse(long) orElse()} | |
* (returns a default value if no value is present) and | |
* {@link #ifPresent(LongConsumer) ifPresent()} (performs an | |
* action if a value is present). | |
* | |
* <p>This is a <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a> | |
* class; programmers should treat instances that are | |
* {@linkplain #equals(Object) equal} as interchangeable and should not | |
* use instances for synchronization, or unpredictable behavior may | |
* occur. For example, in a future release, synchronization may fail. | |
* | |
* @apiNote {@code OptionalLong} is primarily intended for use as a method return type where | |
* there is a clear need to represent "no result." A variable whose type is | |
* {@code OptionalLong} should never itself be {@code null}; it should always point | |
* to an {@code OptionalLong} instance. | |
* @since 1.8 | |
*/ | |
public final class MyOptionalLong { | |
/** | |
* Common instance for {@code empty()}. | |
*/ | |
private static final MyOptionalLong EMPTY = new MyOptionalLong(); | |
private final long value; | |
/** | |
* Construct an empty instance. | |
* | |
* @implNote generally only one empty instance, {@link MyOptionalLong#EMPTY}, | |
* should exist per VM. | |
*/ | |
private MyOptionalLong() { | |
this.value = 0; | |
} | |
/** | |
* Returns an empty {@code OptionalLong} instance. No value is present for | |
* this {@code OptionalLong}. | |
* | |
* @return an empty {@code OptionalLong}. | |
* @apiNote Though it may be tempting to do so, avoid testing if an object is empty | |
* by comparing with {@code ==} or {@code !=} against instances returned by | |
* {@code OptionalLong.empty()}. There is no guarantee that it is a singleton. | |
* Instead, use {@link #isEmpty()} or {@link #isPresent()}. | |
*/ | |
public static MyOptionalLong empty() { | |
return EMPTY; | |
} | |
/** | |
* Construct an instance with the described value. | |
* | |
* @param value the long value to describe | |
*/ | |
private MyOptionalLong(long value) { | |
this.value = value; | |
} | |
/** | |
* Returns an {@code OptionalLong} describing the given value. | |
* | |
* @param value the value to describe | |
* @return an {@code OptionalLong} with the value present | |
*/ | |
public static MyOptionalLong of(long value) { | |
return new MyOptionalLong(value); | |
} | |
/** | |
* If a value is present, returns the value, otherwise throws | |
* {@code NoSuchElementException}. | |
* | |
* @return the value described by this {@code OptionalLong} | |
* @throws NoSuchElementException if no value is present | |
* @apiNote The preferred alternative to this method is {@link #orElseThrow()}. | |
*/ | |
public long getAsLong() { | |
if (!isPresent()) { | |
throw new NoSuchElementException("No value present"); | |
} | |
return value; | |
} | |
/** | |
* If a value is present, returns {@code true}, otherwise {@code false}. | |
* | |
* @return {@code true} if a value is present, otherwise {@code false} | |
*/ | |
public boolean isPresent() { | |
return this != EMPTY; | |
} | |
/** | |
* If a value is not present, returns {@code true}, otherwise | |
* {@code false}. | |
* | |
* @return {@code true} if a value is not present, otherwise {@code false} | |
* @since 11 | |
*/ | |
public boolean isEmpty() { | |
return !isPresent(); | |
} | |
/** | |
* If a value is present, performs the given action with the value, | |
* otherwise does nothing. | |
* | |
* @param action the action to be performed, if a value is present | |
* @throws NullPointerException if value is present and the given action is | |
* {@code null} | |
*/ | |
public void ifPresent(LongConsumer action) { | |
if (isPresent()) { | |
action.accept(value); | |
} | |
} | |
/** | |
* If a value is present, performs the given action with the value, | |
* otherwise performs the given empty-based action. | |
* | |
* @param action the action to be performed, if a value is present | |
* @param emptyAction the empty-based action to be performed, if no value is | |
* present | |
* @throws NullPointerException if a value is present and the given action | |
* is {@code null}, or no value is present and the given empty-based | |
* action is {@code null}. | |
* @since 9 | |
*/ | |
public void ifPresentOrElse(LongConsumer action, Runnable emptyAction) { | |
if (isPresent()) { | |
action.accept(value); | |
} else { | |
emptyAction.run(); | |
} | |
} | |
/** | |
* If a value is present, returns a sequential {@link LongStream} containing | |
* only that value, otherwise returns an empty {@code LongStream}. | |
* | |
* @return the optional value as an {@code LongStream} | |
* @apiNote This method can be used to transform a {@code Stream} of optional longs | |
* to an {@code LongStream} of present longs: | |
* <pre>{@code | |
* Stream<OptionalLong> os = .. | |
* LongStream s = os.flatMapToLong(OptionalLong::stream) | |
* }</pre> | |
* @since 9 | |
*/ | |
public LongStream stream() { | |
if (isPresent()) { | |
return LongStream.of(value); | |
} else { | |
return LongStream.empty(); | |
} | |
} | |
/** | |
* If a value is present, returns the value, otherwise returns | |
* {@code other}. | |
* | |
* @param other the value to be returned, if no value is present | |
* @return the value, if present, otherwise {@code other} | |
*/ | |
public long orElse(long other) { | |
return isPresent() ? value : other; | |
} | |
/** | |
* If a value is present, returns the value, otherwise returns the result | |
* produced by the supplying function. | |
* | |
* @param supplier the supplying function that produces a value to be returned | |
* @return the value, if present, otherwise the result produced by the | |
* supplying function | |
* @throws NullPointerException if no value is present and the supplying | |
* function is {@code null} | |
*/ | |
public long orElseGet(LongSupplier supplier) { | |
return isPresent() ? value : supplier.getAsLong(); | |
} | |
/** | |
* If a value is present, returns the value, otherwise throws | |
* {@code NoSuchElementException}. | |
* | |
* @return the value described by this {@code OptionalLong} | |
* @throws NoSuchElementException if no value is present | |
* @since 10 | |
*/ | |
public long orElseThrow() { | |
if (!isPresent()) { | |
throw new NoSuchElementException("No value present"); | |
} | |
return value; | |
} | |
/** | |
* If a value is present, returns the value, otherwise throws an exception | |
* produced by the exception supplying function. | |
* | |
* @param <X> Type of the exception to be thrown | |
* @param exceptionSupplier the supplying function that produces an | |
* exception to be thrown | |
* @return the value, if present | |
* @throws X if no value is present | |
* @throws NullPointerException if no value is present and the exception | |
* supplying function is {@code null} | |
* @apiNote A method reference to the exception constructor with an empty argument | |
* list can be used as the supplier. For example, | |
* {@code IllegalStateException::new} | |
*/ | |
public <X extends Throwable> long orElseThrow(Supplier<? extends X> exceptionSupplier) throws X { | |
if (isPresent()) { | |
return value; | |
} else { | |
throw exceptionSupplier.get(); | |
} | |
} | |
/** | |
* Indicates whether some other object is "equal to" this | |
* {@code OptionalLong}. The other object is considered equal if: | |
* <ul> | |
* <li>it is also an {@code OptionalLong} and; | |
* <li>both instances have no value present or; | |
* <li>the present values are "equal to" each other via {@code ==}. | |
* </ul> | |
* | |
* @param obj an object to be tested for equality | |
* @return {@code true} if the other object is "equal to" this object | |
* otherwise {@code false} | |
*/ | |
@Override | |
public boolean equals(Object obj) { | |
if (this == obj) { | |
return true; | |
} | |
if (!(obj instanceof MyOptionalLong other)) { | |
return false; | |
} | |
return (isPresent() && other.isPresent()) | |
? value == other.value | |
: isPresent() == other.isPresent(); | |
} | |
/** | |
* Returns the hash code of the value, if present, otherwise {@code 0} | |
* (zero) if no value is present. | |
* | |
* @return hash code value of the present value or {@code 0} if no value is | |
* present | |
*/ | |
@Override | |
public int hashCode() { | |
return isPresent() ? Long.hashCode(value) : 0; | |
} | |
/** | |
* Returns a non-empty string representation of this {@code OptionalLong} | |
* suitable for debugging. The exact presentation format is unspecified and | |
* may vary between implementations and versions. | |
* | |
* @return the string representation of this instance | |
* @implSpec If a value is present the result must include its string representation | |
* in the result. Empty and present {@code OptionalLong}s must be | |
* unambiguously differentiable. | |
*/ | |
@Override | |
public String toString() { | |
return isPresent() | |
? String.format("OptionalLong[%s]", value) | |
: "OptionalLong.empty"; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment