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

com.ajjpj.abase.collection.immutable.AHashSet 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 java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;


/**
 * This is an immutable hash set implementation. It has mutator methods that return a modified copy of the set. It
 *  does not implement java.util.Set because that interface is inherently mutable. It does however
 *  provide a method to return an immutable view implementing java.util.Set.

* * It provides uniqueness guarantees based on a configurable equalityForEquals strategy which defaults to "equals-based". * * @author arno */ public class AHashSet extends AbstractACollection> implements Serializable { private final AHashMap inner; private static final AHashSet emptyEquals = new AHashSet<>(AHashMap.empty(AEquality.EQUALS)); private static final AHashSet emptyIdentity = new AHashSet<>(AHashMap.empty(AEquality.IDENTITY)); /** * Returns an empty AHashSet instance with default (i.e. equals-based) equalityForEquals. Using a factory method instead of * a constructor allows AHashSet to return a cached implementation. */ @SuppressWarnings("unchecked") public static AHashSet empty() { return (AHashSet) emptyEquals; } /** * Returns an empty AHashSet instance with a given equalityForEquals strategy. Using a factory method instead of * a constructor allows AHashSet to return a cached implementation. */ @SuppressWarnings("unchecked") public static AHashSet empty(AEquality equality) { if(equality == AEquality.EQUALS) return (AHashSet) emptyEquals; if(equality == AEquality.IDENTITY) return (AHashSet) emptyIdentity; return new AHashSet<>(AHashMap.empty(equality)); } /** * Creates an AHashSet instance with default (i.e. equals-based) equalityForEquals that is initialized with the elements from a given collection. */ public static AHashSet create(Iterable elements) { return create(AEquality.EQUALS, elements); } /** * Creates an AHashSet instance with a given equalityForEquals strategy that is initialized with the elements from a given collection. */ public static AHashSet create(AEquality equality, Iterable elements) { AHashSet result = empty(equality); for(T el: elements) { result = result.added(el); } return result; } /** * Creates an AHashSet instance with default (i.e. equals-based) equalityForEquals that is initialized with the elements from a given collection. */ @SuppressWarnings("unchecked") public static AHashSet create(T... elements) { return create(AEquality.EQUALS, elements); } /** * Creates an AHashSet instance with a given equalityForEquals strategy that is initialized with the elements from a given collection. */ @SuppressWarnings("unchecked") public static AHashSet create(AEquality equality, T... elements) { AHashSet result = empty(equality); for(T el: elements) { result = result.added(el); } return result; } private AHashSet(AHashMap inner) { this.inner = inner; } @Override protected AHashSet createInternal(Collection elements) { return create(elements); } @Override protected AEquality equalityForEquals() { return inner.equality; } public int size() { return inner.size(); } @SuppressWarnings("unchecked") /** * The parameter is of type Object rather than T to conform to the signature * inherited from java.util.Collection. Passing a reference that is not assignable to * T causes an exception at runtime. */ @Override public boolean contains(Object el) { return inner.containsKey((T) el); } /** * This method creates and returns a new AHashSet instance that is guaranteed to contain the given new element. * 'Containment' is relative to the configured equalityForEquals strategy - if e.g. the set uses AEquality.IDENTITY, it * can contain two objects that are equal without being the same.

* * This is the only method to add elements to the set. */ public AHashSet added(T el) { final AHashMap newInner = inner.updated(el, true); if(newInner == inner) { return this; } return new AHashSet<> (newInner); } /** * This method creates and returns a new AHashSet instance that is guaranteed not to contain the given element. * 'Containment' is relative to the configured equalityForEquals strategy - if e.g. the set uses AEquality.IDENTITY, it * might not remove an element that is equal to the object that is passed to the removed() method * if they are not the same.

* * This is the only method to remove elements from the set. */ public AHashSet removed(T el) { final AHashMap newInner = inner.removed(el); if(newInner == inner) { return this; } return new AHashSet<> (newInner); } /** * Returns a read-only java.util.Set view of this set. The view is read-through, and creation has * constant time complexity. */ public java.util.Set asJavaUtilSet() { return inner.asJavaUtilMap().keySet(); } @Override public Iterator iterator() { return asJavaUtilSet().iterator(); } @Override public int hashCode() { // overridden as an optimization return inner.hashCode(); } @SuppressWarnings("SimplifiableIfStatement") @Override public boolean equals(Object o) { // overridden as an optimization if(o == this) { return true; } if(! (o instanceof AHashSet)) { return false; } return inner.equals(((AHashSet) o).inner); } @Override public AHashSet toSet() { // overridden as an optimization return this; } @Override public AHashSet toSet(AEquality equality) { if(equality == inner.equality) { return this; } return AHashSet.create(equality, this); } @Override public AHashSet map(AFunction1 f) throws E { // list instead of set to support arbitrary equalityForEquals implementations return create(inner.equality, ACollectionHelper.map(this, f)); } @Override public AHashSet flatMap(AFunction1, E> f) throws E { return create(inner.equality, ACollectionHelper.flatMap(this, f)); } @SuppressWarnings("unchecked") @Override public AHashSet flatten() { return (AHashSet) create(inner.equality, ACollectionHelper.flatten((Iterable>) this)); } private Object readResolve () { if (nonEmpty ()) { return this; } return empty (equalityForEquals ()); // used globally cached instances } }