|
@@ -11,15 +11,21 @@ public class FastMap<Value> {
|
|
|
private final List<Key<?>> keys;
|
|
|
private final List<Property<?>> rawKeys;
|
|
|
private final List<Value> values;
|
|
|
+ private final Map<Property<?>, Integer> toKeyIndex;
|
|
|
|
|
|
public FastMap(Collection<Property<?>> properties, Map<Map<Property<?>, Comparable<?>>, Value> valuesMap) {
|
|
|
- List<Key<?>> keys = new ArrayList<>(properties.size());
|
|
|
+ this.rawKeys = ImmutableList.copyOf(properties);
|
|
|
+ List<Key<?>> keys = new ArrayList<>(rawKeys.size());
|
|
|
int factorUpTo = 1;
|
|
|
- for (Property<?> prop : properties) {
|
|
|
+ ImmutableMap.Builder<Property<?>, Integer> toKeyIndex = ImmutableMap.builder();
|
|
|
+ for (Property<?> prop : rawKeys) {
|
|
|
+ toKeyIndex.put(prop, keys.size());
|
|
|
keys.add(new Key<>(prop, factorUpTo));
|
|
|
factorUpTo *= prop.getAllowedValues().size();
|
|
|
}
|
|
|
- this.keys = keys;
|
|
|
+ this.keys = ImmutableList.copyOf(keys);
|
|
|
+ this.toKeyIndex = toKeyIndex.build();
|
|
|
+
|
|
|
List<Value> valuesList = new ArrayList<>(factorUpTo);
|
|
|
for (int i = 0; i < factorUpTo; ++i) {
|
|
|
valuesList.add(null);
|
|
@@ -27,8 +33,7 @@ public class FastMap<Value> {
|
|
|
for (Map.Entry<Map<Property<?>, Comparable<?>>, Value> state : valuesMap.entrySet()) {
|
|
|
valuesList.set(getIndexOf(state.getKey()), state.getValue());
|
|
|
}
|
|
|
- this.values = valuesList;
|
|
|
- this.rawKeys = ImmutableList.copyOf(properties);
|
|
|
+ this.values = ImmutableList.copyOf(valuesList);
|
|
|
}
|
|
|
|
|
|
@Nullable
|
|
@@ -48,14 +53,12 @@ public class FastMap<Value> {
|
|
|
@Nullable
|
|
|
private <T extends Comparable<T>>
|
|
|
Key<T> getKeyFor(Property<T> prop) {
|
|
|
- // It might be possible to speed this up by sorting the keys by their hash code and using a binary search,
|
|
|
- // however I do not think that it would actually be faster in practice.
|
|
|
- for (Key<?> key : keys) {
|
|
|
- if (key.getProperty().equals(prop)) {
|
|
|
- return (Key<T>) key;
|
|
|
- }
|
|
|
+ Integer index = toKeyIndex.get(prop);
|
|
|
+ if (index == null) {
|
|
|
+ return null;
|
|
|
+ } else {
|
|
|
+ return (Key<T>) keys.get(index);
|
|
|
}
|
|
|
- return null;
|
|
|
}
|
|
|
|
|
|
public int getIndexOf(Map<Property<?>, Comparable<?>> state) {
|
|
@@ -97,11 +100,17 @@ public class FastMap<Value> {
|
|
|
private final Property<T> property;
|
|
|
private final List<T> values;
|
|
|
private final int mapFactor;
|
|
|
+ private final Map<Comparable<?>, Integer> toValueIndex;
|
|
|
|
|
|
private Key(Property<T> property, int mapFactor) {
|
|
|
this.property = property;
|
|
|
- this.values = new ArrayList<>(property.getAllowedValues());
|
|
|
+ this.values = ImmutableList.copyOf(property.getAllowedValues());
|
|
|
this.mapFactor = mapFactor;
|
|
|
+ ImmutableMap.Builder<Comparable<?>, Integer> toValueIndex = ImmutableMap.builder();
|
|
|
+ for (int i = 0; i < this.values.size(); i++) {
|
|
|
+ toValueIndex.put(this.values.get(i), i);
|
|
|
+ }
|
|
|
+ this.toValueIndex = toValueIndex.build();
|
|
|
}
|
|
|
|
|
|
public int toPartialMapIndex(Comparable<?> value) {
|
|
@@ -109,8 +118,8 @@ public class FastMap<Value> {
|
|
|
}
|
|
|
|
|
|
private int getInternalIndex(Comparable<?> value) {
|
|
|
- int result = values.indexOf(value);
|
|
|
- if (result >= 0) {
|
|
|
+ Integer result = toValueIndex.get(value);
|
|
|
+ if (result != null) {
|
|
|
return result;
|
|
|
} else {
|
|
|
throw new IllegalStateException("Unknown value: "+value+" in "+property);
|