mirror of
https://github.com/corda/corda.git
synced 2025-01-19 11:16:54 +00:00
Adding EnumSet, which is backed by a speedy BitSet.
This commit is contained in:
parent
d419899ac1
commit
6e30366d07
149
classpath/java/util/EnumSet.java
Normal file
149
classpath/java/util/EnumSet.java
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
package java.util;
|
||||||
|
|
||||||
|
public class EnumSet<T extends Enum<T>> extends AbstractSet<T> {
|
||||||
|
|
||||||
|
private BitSet bitset;
|
||||||
|
private Class<T> elementType;
|
||||||
|
|
||||||
|
private EnumSet(int size, Class<T> type) {
|
||||||
|
bitset = new BitSet(size);
|
||||||
|
elementType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean add(T element) {
|
||||||
|
int index = element.ordinal();
|
||||||
|
boolean contains = bitset.get(index);
|
||||||
|
if (!contains) {
|
||||||
|
bitset.set(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
return !contains;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean remove(Object toRemove) {
|
||||||
|
T element = tryToCast(toRemove);
|
||||||
|
|
||||||
|
int index = element.ordinal();
|
||||||
|
boolean contains = bitset.get(index);
|
||||||
|
if (contains) {
|
||||||
|
bitset.clear(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
return contains;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(Object toCheck) {
|
||||||
|
T element = tryToCast(toCheck);
|
||||||
|
int index = element.ordinal();
|
||||||
|
return bitset.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return bitset.cardinality();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<T> iterator() {
|
||||||
|
return new EnumSetIterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends Enum<T>>EnumSet<T> allOf(Class<T> elementType) {
|
||||||
|
EnumSet<T> enumSet = createEmptyEnumSet(elementType);
|
||||||
|
addAllElementsToSet(Arrays.asList(elementType.getEnumConstants()), enumSet);
|
||||||
|
|
||||||
|
return enumSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends Enum<T>>EnumSet<T> noneOf(Class<T> elementType) {
|
||||||
|
return createEmptyEnumSet(elementType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends Enum<T>>EnumSet<T> of(T first, T ... rest) {
|
||||||
|
EnumSet<T> enumSet = createEmptyEnumSet(first.getDeclaringClass());
|
||||||
|
enumSet.add(first);
|
||||||
|
addAllElementsToSet(Arrays.asList(rest), enumSet);
|
||||||
|
|
||||||
|
return enumSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends Enum<T>>EnumSet<T> complementOf(EnumSet<T> s) {
|
||||||
|
EnumSet<T> enumSet = copyOf(s);
|
||||||
|
enumSet.bitset.flip(0, s.elementType.getEnumConstants().length);
|
||||||
|
|
||||||
|
return enumSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends Enum<T>>EnumSet<T> copyOf(EnumSet<T> s) {
|
||||||
|
EnumSet<T> enumSet = createEmptyEnumSet(s.elementType);
|
||||||
|
enumSet.bitset.or(s.bitset);
|
||||||
|
|
||||||
|
return enumSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T extends Enum<T>>EnumSet<T> createEmptyEnumSet(Class<T> elementType) {
|
||||||
|
T[] constants = elementType.getEnumConstants();
|
||||||
|
EnumSet<T> enumSet = new EnumSet<T>(constants.length, elementType);
|
||||||
|
|
||||||
|
return enumSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T extends Enum<T>> void addAllElementsToSet(Iterable<T> elements, EnumSet<T> enumSet) {
|
||||||
|
for (T element : elements) {
|
||||||
|
enumSet.add(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private T tryToCast(Object object) throws ClassCastException {
|
||||||
|
//We want the class cast exception if we can't convert.
|
||||||
|
return (T) object;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class EnumSetIterator implements Iterator<T> {
|
||||||
|
private int currentIndex = 0;
|
||||||
|
private boolean removeAllowed = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T next() {
|
||||||
|
if (!hasNext()) {
|
||||||
|
throw new NoSuchElementException("EnumSet has no more elements");
|
||||||
|
}
|
||||||
|
|
||||||
|
int indexOfNextValue = nextIndex();
|
||||||
|
T element = elementType.getEnumConstants()[indexOfNextValue];
|
||||||
|
currentIndex = indexOfNextValue + 1;
|
||||||
|
removeAllowed = true;
|
||||||
|
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
int indexOfNextValue = nextIndex();
|
||||||
|
if (indexOfNextValue >= 0) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
//TODO
|
||||||
|
if (!removeAllowed) {
|
||||||
|
throw new IllegalStateException("Cannot remove from this iterator in this state");
|
||||||
|
}
|
||||||
|
|
||||||
|
bitset.clear(currentIndex - 1);
|
||||||
|
removeAllowed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int nextIndex() {
|
||||||
|
return bitset.nextSetBit(currentIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
107
test/EnumSetTest.java
Normal file
107
test/EnumSetTest.java
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
public class EnumSetTest {
|
||||||
|
private enum SmallEnum {
|
||||||
|
ONE,
|
||||||
|
TWO,
|
||||||
|
THREE
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum LargerEnum {
|
||||||
|
LARGEONE,
|
||||||
|
LARGETWO,
|
||||||
|
LARGETHREE,
|
||||||
|
LARGEFOUR,
|
||||||
|
LARGEFIVE,
|
||||||
|
LARGESIX
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
testAllOf();
|
||||||
|
testNoneOf();
|
||||||
|
testIterators();
|
||||||
|
testOf();
|
||||||
|
testCopyOf();
|
||||||
|
testComplimentOf();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testComplimentOf() {
|
||||||
|
EnumSet<SmallEnum> one = EnumSet.of(SmallEnum.ONE, SmallEnum.THREE);
|
||||||
|
EnumSet<SmallEnum> two = EnumSet.complementOf(one);
|
||||||
|
assertElementInSet(SmallEnum.TWO, two);
|
||||||
|
assertSize(1, two);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testCopyOf() {
|
||||||
|
EnumSet<SmallEnum> one = EnumSet.of(SmallEnum.ONE, SmallEnum.THREE);
|
||||||
|
EnumSet<SmallEnum> two = EnumSet.copyOf(one);
|
||||||
|
assertElementInSet(SmallEnum.ONE, two);
|
||||||
|
assertElementInSet(SmallEnum.THREE, two);
|
||||||
|
assertSize(2, two);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testOf() {
|
||||||
|
EnumSet<LargerEnum> set = EnumSet.of(LargerEnum.LARGEONE, LargerEnum.LARGEFIVE, LargerEnum.LARGETWO);
|
||||||
|
assertElementInSet(LargerEnum.LARGEONE, set);
|
||||||
|
assertElementInSet(LargerEnum.LARGEFIVE, set);
|
||||||
|
assertElementInSet(LargerEnum.LARGETWO, set);
|
||||||
|
assertSize(3, set);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testAllOf() {
|
||||||
|
EnumSet<SmallEnum> set = EnumSet.allOf(SmallEnum.class);
|
||||||
|
for (SmallEnum current : SmallEnum.values()) {
|
||||||
|
assertElementInSet(current, set);
|
||||||
|
}
|
||||||
|
assertSize(3, set);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testNoneOf() {
|
||||||
|
EnumSet<SmallEnum> set = EnumSet.noneOf(SmallEnum.class);
|
||||||
|
assertSize(0, set);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testIterators() {
|
||||||
|
EnumSet<SmallEnum> set = EnumSet.allOf(SmallEnum.class);
|
||||||
|
Iterator<SmallEnum> iterator = set.iterator();
|
||||||
|
boolean exceptionCaught = false;
|
||||||
|
try {
|
||||||
|
iterator.remove();
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
exceptionCaught = true;
|
||||||
|
}
|
||||||
|
if (!exceptionCaught) {
|
||||||
|
throw new RuntimeException("Calling remove() before next() should throw IllegalStateException");
|
||||||
|
}
|
||||||
|
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
iterator.next();
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
assertSize(0, set);
|
||||||
|
|
||||||
|
exceptionCaught = false;
|
||||||
|
try {
|
||||||
|
iterator.next();
|
||||||
|
} catch (NoSuchElementException e) {
|
||||||
|
exceptionCaught = true;
|
||||||
|
}
|
||||||
|
if (!exceptionCaught) {
|
||||||
|
throw new RuntimeException("Calling next() when hasNext() == false should throw NoSuchElementException");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void assertElementInSet(Enum<?> element, EnumSet<?> set) {
|
||||||
|
if (!set.contains(element)) {
|
||||||
|
throw new RuntimeException("expected " + element + " in the set!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void assertSize(int expectedSize, EnumSet<?> set) {
|
||||||
|
if (set.size() != expectedSize) {
|
||||||
|
throw new RuntimeException("expected the set to be size=" + expectedSize + ", actual=" + set.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user