blob: 3b20535ea3417ba6eb944a8eee3f67b5d68a17f9 [file] [log] [blame]
package org.checkerframework.dataflow.util;
import java.util.LinkedHashSet;
import org.checkerframework.javacutil.BugInCF;
/**
* A set that is more efficient than HashSet for 0 and 1 elements. Uses {@code Objects.equals} for
* object comparison and a {@link LinkedHashSet} for backing storage.
*/
public final class MostlySingleton<T extends Object> extends AbstractMostlySingleton<T> {
/** Create a MostlySingleton. */
public MostlySingleton() {
super(State.EMPTY);
}
/** Create a MostlySingleton. */
public MostlySingleton(T value) {
super(State.SINGLETON, value);
}
@Override
public boolean add(T e) {
switch (state) {
case EMPTY:
state = State.SINGLETON;
value = e;
return true;
case SINGLETON:
assert value != null : "@AssumeAssertion(nullness): SINGLETON => value != null";
if (value.equals(e)) {
return false;
}
makeNonSingleton();
// fall through
case ANY:
assert set != null : "@AssumeAssertion(nullness): ANY => value != null";
return set.add(e);
default:
throw new BugInCF("Unhandled state " + state);
}
}
/** Switch the representation of this from SINGLETON to ANY. */
private void makeNonSingleton() {
state = State.ANY;
set = new LinkedHashSet<>();
assert value != null : "@AssumeAssertion(nullness): SINGLETON => value != null";
set.add(value);
value = null;
}
@Override
public boolean contains(Object o) {
switch (state) {
case EMPTY:
return false;
case SINGLETON:
assert value != null : "@AssumeAssertion(nullness): SINGLETON => value != null";
return value.equals(o);
case ANY:
assert set != null : "@AssumeAssertion(nullness): set initialized before";
return set.contains(o);
default:
throw new BugInCF("Unhandled state " + state);
}
}
}