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

com.ajjpj.abase.collection.immutable.AOption Maven / Gradle / Ivy

Go to download

a-base is a library of basic (hence the name) classes, most notably immutable collection classes with copy-on-write operations

There is a newer version: 1.0-pre11
Show newest version
package com.ajjpj.abase.collection.immutable;

import com.ajjpj.abase.collection.ACollectionHelper;
import com.ajjpj.abase.collection.AEquality;
import com.ajjpj.abase.function.AFunction1;
import com.ajjpj.abase.function.AFunction2;
import com.ajjpj.abase.function.APredicate;
import com.ajjpj.abase.function.AStatement1;

import java.io.Serializable;
import java.util.*;


/**
 * This class represents an object that may or may not be present. It is intended as a more explicit, less error prone
 *  replacement for using null to represent the absence of a value.

* * There are two flavors of AOption: AOption.some(...) and AOption.none(). * AOption.some(x) represents the presence of a value, namely 'x', while AOption.none() * represents 'no value'.

* * There are two key reasons for using this class instead of using null to encode the absence of a value.

* * Firstly, AOption explicitly shows in the code that a value is optional, forcing code to explicitly deal * with that fact. A method returning a value that may or may not be present (e.g. a call to get(...) on * a map) can specify AOption as its return type to make that characteristic explicit.

* * Secondly, code can operate on an AOption regardless of whether there is a value or not (e.g. by calling * map()). This functional style of programming can make for code that is easier to read and less cluttered * than having if statements checking for the presence of values all over the place.

* * This class was inspired by the Option class from the Scala standard library. Thanks for the excellent * code, Scala team! * * @author arno */ public abstract class AOption implements ACollection, Serializable { public static AOption some(T el) { return new ASome<>(el); } @SuppressWarnings("unchecked") public static AOption none() { return (AOption) ANone.INSTANCE; } public static AOption fromNullable(T nullable) { return nullable != null ? some(nullable) : AOption.none(); } public abstract boolean isDefined(); public boolean isEmpty() { return !isDefined(); } public abstract T get(); public T getOrElse(T el) { return isDefined() ? get() : el; } @Override public ATraversable flatMap(AFunction1, E> f) throws E { throw new UnsupportedOperationException("AOption can not be flattened"); } @Override public ACollection flatten() { throw new UnsupportedOperationException("AOption can not be flattened"); } @Override public String mkString() { return ACollectionHelper.mkString(this); } @Override public String mkString(String separator) { return ACollectionHelper.mkString(this, separator); } @Override public String mkString(String prefix, String separator, String suffix) { return ACollectionHelper.mkString(this, prefix, separator, suffix); } public abstract boolean equals(Object o); public abstract int hashCode(); static class ASome extends AOption { private final T el; ASome(T el) { this.el = el; } @Override public T get() { return el; } @Override public boolean isDefined() { return true; } @Override public void forEach(AStatement1 f) throws E { f.apply(el); } @Override public AOption find(APredicate pred) throws E { return filter(pred); } @Override public AOption map(AFunction1 f) throws E { return some(f.apply(el)); } @Override public AOption filter(APredicate pred) throws E { if(pred.apply(el)) return this; else return none(); } @Override public R foldLeft (R startValue, AFunction2 f) throws E { return f.apply(startValue, el); } @Override public int size() { return 1; } @Override public boolean nonEmpty() { return true; } @Override public boolean forAll(APredicate pred) throws E { return find(pred).isDefined(); } @Override public boolean exists(APredicate pred) throws E { return find(pred).isDefined(); } @Override public AMap> groupBy(AFunction1 f) throws E { return groupBy(f, AEquality.EQUALS); } @Override public AMap> groupBy(AFunction1 f, AEquality keyEquality) throws E { //TODO junit final AMap> result = AHashMap.empty(keyEquality); return result.updated(f.apply(el), this); } @Override public AList toList() { return AList.nil().cons(el); } @Override public AHashSet toSet() { return AHashSet.empty().added(el); } @Override public AHashSet toSet(AEquality equality) { return AHashSet.empty(equality).added(el); } @SuppressWarnings("NullableProblems") @Override public Iterator iterator() { return Collections.singletonList(el).iterator(); } @Override public String toString() { return "AOption.some(" + el + ")"; } @SuppressWarnings("RedundantIfStatement") @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ASome aSome = (ASome) o; if (el != null ? !el.equals(aSome.el) : aSome.el != null) return false; return true; } @Override public int hashCode() { return el != null ? el.hashCode() : 0; } @Override public boolean contains(Object o) { return AEquality.EQUALS.equals(el, o); } @SuppressWarnings("NullableProblems") @Override public Object[] toArray() { return new Object[] {el}; } @SuppressWarnings({"NullableProblems", "SuspiciousToArrayCall"}) @Override public T1[] toArray(T1[] a) { return Arrays.asList(el).toArray(a); } @Override public boolean add(T t) { throw new UnsupportedOperationException(); } @Override public boolean remove(Object o) { throw new UnsupportedOperationException(); } @SuppressWarnings({"NullableProblems", "SimplifiableIfStatement"}) @Override public boolean containsAll(Collection c) { if(c.isEmpty()) { return true; } return c.size() == 1 && c.contains(el); } @SuppressWarnings("NullableProblems") @Override public boolean addAll(Collection c) { throw new UnsupportedOperationException(); } @SuppressWarnings("NullableProblems") @Override public boolean removeAll(Collection c) { throw new UnsupportedOperationException(); } @SuppressWarnings("NullableProblems") @Override public boolean retainAll(Collection c) { throw new UnsupportedOperationException(); } @Override public void clear() { throw new UnsupportedOperationException(); } } static class ANone extends AOption { public static final ANone INSTANCE = new ANone(); private ANone() {} private Object readResolve() { return INSTANCE; } @Override public Object get() { throw new NoSuchElementException("no value for ANone"); } @Override public boolean isDefined() { return false; } @Override public void forEach(AStatement1 f) { // nothing to be done } @Override public AOption find(APredicate pred) throws E { return none(); } @Override public AOption map(AFunction1 f) { return none(); } @Override public R foldLeft (R startValue, AFunction2 f) throws E { return startValue; } @Override public AOption filter(APredicate pred) { return none(); } @Override public boolean nonEmpty() { return true; } @Override public int size() { return 0; } @Override public boolean forAll(APredicate pred) throws E { return true; } @Override public boolean exists(APredicate pred) throws E { return false; } @Override public AMap> groupBy(AFunction1 f) throws E { return AHashMap.empty(); //TODO junit } @Override public AMap> groupBy(AFunction1 f, AEquality keyEquality) throws E { return AHashMap.empty(keyEquality); //TODO junit } @Override public AList toList() { return AList.nil(); } @Override public AHashSet toSet() { return AHashSet.empty(); } @Override public AHashSet toSet(AEquality equality) { return AHashSet.empty(equality); } @SuppressWarnings("NullableProblems") @Override public Iterator iterator() { return Collections.emptyList().iterator(); } @Override public String toString() { return "AOption.none()"; } @Override public boolean equals(Object o) { return o == this; } @Override public int hashCode() { return 0; } @Override public boolean contains(Object o) { return false; } @SuppressWarnings("NullableProblems") @Override public Object[] toArray() { return new Object[0]; } @SuppressWarnings("NullableProblems") @Override public T[] toArray(T[] a) { if(a.length > 0) { a[0] = null; } return a; } @Override public boolean add(Object o) { throw new UnsupportedOperationException(); } @Override public boolean remove(Object o) { throw new UnsupportedOperationException(); } @SuppressWarnings("NullableProblems") @Override public boolean containsAll(Collection c) { return c.isEmpty(); } @SuppressWarnings("NullableProblems") @Override public boolean addAll(Collection c) { throw new UnsupportedOperationException(); } @SuppressWarnings("NullableProblems") @Override public boolean removeAll(Collection c) { throw new UnsupportedOperationException(); } @SuppressWarnings("NullableProblems") @Override public boolean retainAll(Collection c) { throw new UnsupportedOperationException(); } @Override public void clear() { throw new UnsupportedOperationException(); } } }