|
|
@@ -0,0 +1,185 @@
|
|
|
+package net.ranides.assira.collection.sets;
|
|
|
+
|
|
|
+import java.util.AbstractSet;
|
|
|
+import java.util.Collection;
|
|
|
+import java.util.Iterator;
|
|
|
+import java.util.NoSuchElementException;
|
|
|
+
|
|
|
+/**
|
|
|
+ * This class extends standard Set collection, providing additional functionality.
|
|
|
+ * - offers conversion of set into int
|
|
|
+ * - offers fast conversion into mutable or immutable MaskSet
|
|
|
+ * <p>
|
|
|
+ * This class can be created directly. You must use MaskFactory to obtain instances of this class.
|
|
|
+ *
|
|
|
+ * @param <T> type of
|
|
|
+ */
|
|
|
+public abstract class MaskSet<T> extends AbstractSet<T> {
|
|
|
+
|
|
|
+ protected final MaskFactory<T> factory;
|
|
|
+
|
|
|
+ protected MaskSet(MaskFactory<T> factory) {
|
|
|
+ this.factory = factory;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Converts this mask into int value.
|
|
|
+ *
|
|
|
+ * @return int
|
|
|
+ */
|
|
|
+ public abstract int intValue();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Converts this mask into mutable set.
|
|
|
+ *
|
|
|
+ * @return new mask
|
|
|
+ */
|
|
|
+ public final MaskSet<T> toMutable() {
|
|
|
+ return new MutableSet<>(factory, intValue());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Converts this mask into immutable set.
|
|
|
+ *
|
|
|
+ * @return new mask
|
|
|
+ */
|
|
|
+ public final MaskSet<T> toImmutable() {
|
|
|
+ return new ImmutableSet<>(factory, intValue());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final Iterator<T> iterator() {
|
|
|
+ return new ConstIterator<>(factory, intValue());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final int size() {
|
|
|
+ return Integer.bitCount(intValue());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final boolean contains(Object object) {
|
|
|
+ if (!factory.type.isInstance(object)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ int v = factory.objectToInt(object);
|
|
|
+ return v == (intValue() & v);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final boolean containsAll(Collection<?> object) {
|
|
|
+ if (object instanceof MaskSet) {
|
|
|
+ MaskSet<?> that = (MaskSet<?>) object;
|
|
|
+ if (this.factory == that.factory) {
|
|
|
+ return that.intValue() == (this.intValue() & that.intValue());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return super.containsAll(object);
|
|
|
+ }
|
|
|
+
|
|
|
+ static class ImmutableSet<T> extends MaskSet<T> {
|
|
|
+
|
|
|
+ private final int values;
|
|
|
+
|
|
|
+ public ImmutableSet(MaskFactory<T> factory, int values) {
|
|
|
+ super(factory);
|
|
|
+ this.values = values;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int intValue() {
|
|
|
+ return values;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ static class MutableSet<T> extends MaskSet<T> {
|
|
|
+
|
|
|
+ private int values;
|
|
|
+
|
|
|
+ public MutableSet(MaskFactory<T> factory, int values) {
|
|
|
+ super(factory);
|
|
|
+ this.values = values;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int intValue() {
|
|
|
+ return values;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean remove(Object value) {
|
|
|
+ if(!factory.type.isInstance(value)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ int iv = factory.objectToInt(value);
|
|
|
+ if(0 == (values & iv)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ values &= ~iv;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean add(T value) {
|
|
|
+ return iadd(factory.genericToInt(value));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean addAll(Collection<? extends T> object) {
|
|
|
+ if(object instanceof MaskSet) {
|
|
|
+ MaskSet<?> that = (MaskSet<?>)object;
|
|
|
+ if(this.factory == that.factory) {
|
|
|
+ return iadd(that.intValue());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return super.addAll(object);
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean iadd(int iv) {
|
|
|
+ if(iv == (values & iv)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ values |= iv;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private static final class ConstIterator<T> implements Iterator<T> {
|
|
|
+
|
|
|
+ private final MaskFactory<T> factory;
|
|
|
+ private int value;
|
|
|
+ private int index;
|
|
|
+
|
|
|
+ public ConstIterator(MaskFactory<T> factory, int value) {
|
|
|
+ this.factory = factory;
|
|
|
+ this.value = value;
|
|
|
+ this.index = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean hasNext() {
|
|
|
+ return 0 != value;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public T next() {
|
|
|
+ try {
|
|
|
+ while(value!=0) {
|
|
|
+ T item = factory.universe[index++];
|
|
|
+ int iv = factory.genericToInt(item);
|
|
|
+ if( 0 != (value & iv) ) {
|
|
|
+ value &= ~iv;
|
|
|
+ return item;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch(IndexOutOfBoundsException cause) {
|
|
|
+ throw new NoSuchElementException(factory.unknownValueMessage(value));
|
|
|
+ }
|
|
|
+ throw new NoSuchElementException();
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+}
|