All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javascalautils.Option Maven / Gradle / Ivy

There is a newer version: 1.11.2
Show newest version
/**
 * Copyright 2015 Peter Nerg
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package javascalautils;

import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;

/**
 * Represents optional values. 
* Instances of Option are either an instance of {@link Some} or {@link None}.
* {@link Some} holds a non-null value whilst {@link None} holds no value.
* The primary use case is to replace ugly null-checks.
* Consider the method:
* *
* *
 * SomeData getDataIfExists(SomeInput input) {
 *   if(haveData(input) {
 *      return getSomeDataFromInternalStorage();
 *   }
 *   return null;
 * }
 * 
* *
* * The above method causes the user to do null-checks in case the method returned a proper value or not.
* A neater way would be: * *
* *
 * Option<SomeData> getDataIfExists(SomeInput input) {
 *   if(haveData(input) {
 *      return new Some<>(getSomeDataFromInternalStorage());
 *   }
 *   return Option.None();
 * }
 * 
* *
* * Another example is the usage of {@link java.util.Map Maps}.
* Performing a get on a Map will either yield the value of the key or null if no such key existed.
* Consider the Map:
*
Map<String, SomeData> map = ....

* To avoid null checks one could do like so:
*
Option<SomeData> option = Option.apply(map.get("someKey"));
Now you have a guaranteed non-null value with which you can work * with without performing constant null-checks.
* Statically importing methods from the companion class ({@link OptionCompanion}) to Option one can get that Scala feel of declaration.
*
* *
 * import static javascalautils.OptionCompanion.Option;
 * 
 * Option<String> option = Option(map.get("someKey"));
 * 
* *
* * @author Peter Nerg * @since 1.0 * @param * The type of the value represented by this instance */ public interface Option extends Iterable { /** * This is a singleton {@link None} since it anyways cannot represent a state.
* Can also be accessed using {@link #empty()} */ @SuppressWarnings("rawtypes") None DEFAULT_NONE = new None(); /** * Creates an instance of Option.
* If a null value is provided then {@link None} is returned, else {@link Some} containing the provided value. * * @param * The type for the value this Option represents * @param value * The value this Option shall represent * @return The Option representing the provided value * @since 1.0 */ static Option apply(T value) { return value != null ? new Some<>(value) : None(); } /** * Returns an empty Option.
* In practice this returns a {@link #DEFAULT_NONE singleton} as it anyways cannot represent a value/state. * * @param * The type for the value this Option represents * @return The default {@link None} instance * @since 1.0 */ static Option empty() { return None(); } /** * Returns an empty Option.
* This is the same as {@link #empty()} but with the difference it provides a more Scala like feeling if the method is statically imported.
* One can use None() as if it was a apply method on a companion object in Scala.
* E.g. * *
* *
     * import static javascalautils.Option.None;
     * 
     * Option<String> opt = None();
     * 
* *
* * * @param * The type for the value this Option represents * @return The default {@link None} instance * @since 1.2 */ @SuppressWarnings("unchecked") static Option None() { return DEFAULT_NONE; } /** * Returns true if this is a {@link Some} containing the provided object, else false. * * @param other * The other object to compare to * @return If this {@link Some} contains the provided object * @since 1.0 */ default boolean contains(final T other) { return exists(value -> value.equals(other)); } /** * Returns the count which means 1 for nonempty Option's and 0 for empty. * * @return The count * @since 1.0 */ default int count() { // map will either return Some(1) or None upon which the else(0) will be returned. return map(value -> 1).getOrElse(() -> 0); } /** * Returns true if this option is nonempty and the predicate p returns true when applied to this Option's value. * * @param predicate * The predicate * @return If the predicate matches * @since 1.0 */ boolean exists(Predicate predicate); /** * Returns this Option if it is nonempty and applying the predicate p to this Option's value returns true. * * @param predicate * The predicate * @return The Option representing the match * @since 1.0 */ default Option filter(Predicate predicate) { return exists(predicate) ? this : None(); } /** * Returns this Option if it is nonempty and applying the predicate p to this Option's value returns false. * * @param predicate * The predicate * @return The Option representing the match * @since 1.0 */ default Option filterNot(final Predicate predicate) { // filter not is in practice just negating the result of the provided predicate return filter(value -> !predicate.test(value)); } /** * Returns true if the Option is nonempty and the predicate holds true, else false.
* As an {@link Option} is a zero-or-one sized collection this is in an essence exactly the same as {@link #exists(Predicate)}. * * @param predicate * The predicate * @return If the predicate matches * @since 1.0 */ default boolean forall(Predicate predicate) { return exists(predicate); } /** * Returns this Option's value if such exists, else {@link NoSuchElementException} is raised. * * @return The value of the Option * @since 1.0 */ T get(); /** * Returns this Option's value if such exists, else the value provided by the supplier. * * @param supplier * The supplier to use in case this is a {@link None} * @return The value of the Option or the value provided by the supplier * @since 1.0 */ T getOrElse(Supplier supplier); /** * Returns true if the option is an instance of {@link Some}, false otherwise. * * @return true this Option is a {@link Some}, else false * @since 1.0 */ default boolean isDefined() { return exists(t -> true); } /** * Returns true if the option is an instance of {@link None}, false otherwise * * @return true this Option is a {@link None}, else false * @since 1.0 */ default boolean isEmpty() { return !isDefined(); } /** * Returns the Option's value in an {@link Iterator} if it is nonempty, or an empty {@link Iterator} if it is empty. * * @return The iterator for the Option * @since 1.0 */ @Override Iterator iterator(); /** * Returns an Option consisting of the result of applying the given function to the current {@link Some}.
* Applying map to {@link None} will always yield {@link None}. * * @param * The type for the return value from the function * @param function * The function to use * @return The Option containing the mapped value * @since 1.0 */ Option map(Function function); /** * Returns an Option consisting of the result of applying the given function to the current {@link Some}.
* Applying map to {@link None} will always yield {@link None}. * * @param * The type for the return value from the function * @param function * The function to use * @return The Option containing the mapped value * @since 1.2 */ Option flatMap(Function> function); /** * Returns this Option if it is nonempty, otherwise return the result of provided by the supplier. * * @param supplier * The supplier to use in case of {@link None} * @return This Option or the one provided by the supplier * @since 1.0 */ Option orElse(Supplier> supplier); /** * Returns the Option's value if it is nonempty, or null if it is empty. * * @return The value of the Option or null in case of {@link None} * @since 1.0 */ default T orNull() { return getOrElse(() -> null); } /** * Returns the Option's value in a Stream if it is nonempty, or an empty Stream if it is empty. * * @return The stream for the Option * @since 1.0 */ Stream stream(); /** * Returns the value of this {@link Some} as a {@link Left}, or in case of {@link None} a {@link Right} containing the value from the provided supplier. * * @param * The type in case {@link Right} returned * @param right * The supplier to use in case this is a {@link None} * @return The {@link Either} instance * @since 1.4 */ Either toLeft(Supplier right); /** * Returns the value of this {@link Some} as a {@link Right}, or in case of {@link None} a {@link Left} containing the value from the provided supplier. * * @param * The type in case {@link Left} returned * @param left * The supplier to use in case this is a {@link None} * @return The {@link Either} instance * @since 1.4 */ Either toRight(Supplier left); /** * Converts this {@link Option} to a corresponding {@link Optional}. * * @return The Optional instance * @since 1.0 */ default Optional asOptional() { return Optional.ofNullable(orNull()); } /** * Converts the {@link Optional} to a corresponding {@link Option}. * * @param * The type for the value this Option represents * @param optional * The Optional to convert * @return The Option for the provided Optional * @since 1.0 */ static Option ofOptional(Optional optional) { return apply(optional.orElse(null)); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy