package org.checkerframework.dataflow.util; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Set; /** * A set that is more efficient than HashSet for 0 and 1 elements. */ final public class MostlySingleton<T> implements Set<T> { private enum State { EMPTY, SINGLETON, ANY } private State state = State.EMPTY; private T value; private HashSet<T> set; @Override public int size() { switch (state) { case EMPTY: return 0; case SINGLETON: return 1; case ANY: return set.size(); default: throw new AssertionError(); } } @Override public boolean isEmpty() { return size() == 0; } @Override public boolean contains(Object o) { switch (state) { case EMPTY: return false; case SINGLETON: return Objects.equals(o, value); case ANY: return set.contains(o); default: throw new AssertionError(); } } @Override @SuppressWarnings("fallthrough") public boolean add(T e) { switch (state) { case EMPTY: state = State.SINGLETON; value = e; return true; case SINGLETON: state = State.ANY; set = new HashSet<T>(); set.add(value); value = null; // fallthrough case ANY: return set.add(e); default: throw new AssertionError(); } } @Override public Iterator<T> iterator() { switch (state) { case EMPTY: return Collections.emptyIterator(); case SINGLETON: return new Iterator<T>() { private boolean hasNext = true; @Override public boolean hasNext() { return hasNext; } @Override public T next() { if (hasNext) { hasNext = false; return value; } throw new NoSuchElementException(); } @Override public void remove() { throw new UnsupportedOperationException(); } }; case ANY: return set.iterator(); default: throw new AssertionError(); } } @Override public Object[] toArray() { throw new UnsupportedOperationException(); } @Override public <S> S[] toArray(S[] a) { throw new UnsupportedOperationException(); } @Override public boolean remove(Object o) { throw new UnsupportedOperationException(); } @Override public boolean containsAll(Collection<?> c) { throw new UnsupportedOperationException(); } @Override public boolean addAll(Collection<? extends T> c) { throw new UnsupportedOperationException(); } @Override public boolean retainAll(Collection<?> c) { throw new UnsupportedOperationException(); } @Override public boolean removeAll(Collection<?> c) { throw new UnsupportedOperationException(); } @Override public void clear() { throw new UnsupportedOperationException(); } }