package com.carrotsearch.hppc;
import java.util.*;
import com.carrotsearch.hppc.cursors.*;
import com.carrotsearch.hppc.predicates.*;
import com.carrotsearch.hppc.procedures.*;
import static com.carrotsearch.hppc.HashContainers.*;
import static com.carrotsearch.hppc.Containers.*;
@SuppressWarnings("unchecked")
@com.carrotsearch.hppc.Generated(
date = "2018-05-21T12:24:05+0200",
value = "KTypeVTypeHashMap.java")
public class ObjectCharHashMap<KType>
implements
ObjectCharMap<KType>,
Preallocable,
Cloneable
{
public
Object []
keys;
public char []
values;
protected int keyMixer;
protected int assigned;
protected int mask;
protected int resizeAt;
protected boolean hasEmptyKey;
protected double loadFactor;
protected HashOrderMixingStrategy orderMixer;
public ObjectCharHashMap() {
this(DEFAULT_EXPECTED_ELEMENTS);
}
public ObjectCharHashMap(int expectedElements) {
this(expectedElements, DEFAULT_LOAD_FACTOR);
}
public ObjectCharHashMap(int expectedElements, double loadFactor) {
this(expectedElements, loadFactor, HashOrderMixing.defaultStrategy());
}
public ObjectCharHashMap(int expectedElements, double loadFactor, HashOrderMixingStrategy orderMixer) {
this.orderMixer = orderMixer;
this.loadFactor = verifyLoadFactor(loadFactor);
ensureCapacity(expectedElements);
}
public ObjectCharHashMap(ObjectCharAssociativeContainer<? extends KType> container) {
this(container.size());
putAll(container);
}
@Override
public char put(KType key, char value) {
assert assigned < mask + 1;
final int mask = this.mask;
if (((key) == null)) {
hasEmptyKey = true;
char previousValue = values[mask + 1];
values[mask + 1] = value;
return previousValue;
} else {
final KType[] keys = (KType[]) this.keys;
int slot = hashKey(key) & mask;
KType existing;
while (!((existing = keys[slot]) == null)) {
if (this.equals(existing, key)) {
final char previousValue = values[slot];
values[slot] = value;
return previousValue;
}
slot = (slot + 1) & mask;
}
if (assigned == resizeAt) {
allocateThenInsertThenRehash(slot, key, value);
} else {
keys[slot] = key;
values[slot] = value;
}
assigned++;
return ((char) 0);
}
}
@Override
public int putAll(ObjectCharAssociativeContainer<? extends KType> container) {
final int count = size();
for (ObjectCharCursor<? extends KType> c : container) {
put(c.key, c.value);
}
return size() - count;
}
@Override
public int putAll(Iterable<? extends ObjectCharCursor<? extends KType>> iterable){
final int count = size();
for (ObjectCharCursor<? extends KType> c : iterable) {
put(c.key, c.value);
}
return size() - count;
}
public boolean putIfAbsent(KType key, char value) {
int keyIndex = indexOf(key);
if (!indexExists(keyIndex)) {
indexInsert(keyIndex, key, value);
return true;
} else {
return false;
}
}
@Override
public char putOrAdd(KType key, char putValue, char incrementValue) {
assert assigned < mask + 1;
int keyIndex = indexOf(key);
if (indexExists(keyIndex)) {
putValue = ((char) (( values[keyIndex]) + (incrementValue)));
indexReplace(keyIndex, putValue);
} else {
indexInsert(keyIndex, key, putValue);
}
return putValue;
}
@Override
public char addTo(KType key, char incrementValue)
{
return putOrAdd(key, incrementValue, incrementValue);
}
@Override
public char remove(KType key) {
final int mask = this.mask;
if (((key) == null)) {
hasEmptyKey = false;
char previousValue = values[mask + 1];
values[mask + 1] = ((char) 0);
return previousValue;
} else {
final KType[] keys = (KType[]) this.keys;
int slot = hashKey(key) & mask;
KType existing;
while (!((existing = keys[slot]) == null)) {
if (this.equals(existing, key)) {
final char previousValue = values[slot];
shiftConflictingKeys(slot);
return previousValue;
}
slot = (slot + 1) & mask;
}
return ((char) 0);
}
}
@Override
public int removeAll(ObjectContainer<? super KType> other) {
final int before = size();
if (other.size() >= size() &&
other instanceof ObjectLookupContainer<?>) {
if (hasEmptyKey) {
if (other.contains(null)) {
hasEmptyKey = false;
values[mask + 1] = ((char) 0);
}
}
final KType[] keys = (KType[]) this.keys;
for (int slot = 0, max = this.mask; slot <= max;) {
KType existing;
if (!((existing = keys[slot]) == null) && other.contains(existing)) {
shiftConflictingKeys(slot);
} else {
slot++;
}
}
} else {
for (ObjectCursor<?> c : other) {
this.remove((KType) c.value);
}
}
return before - size();
}
@Override
public int removeAll(ObjectCharPredicate<? super KType> predicate) {
final int before = size();
final int mask = this.mask;
if (hasEmptyKey) {
if (predicate.apply(null, values[mask + 1])) {
hasEmptyKey = false;
values[mask + 1] = ((char) 0);
}
}
final KType[] keys = (KType[]) this.keys;
final char[] values = this.values;
for (int slot = 0; slot <= mask;) {
KType existing;
if (!((existing = keys[slot]) == null) &&
predicate.apply(existing, values[slot])) {
shiftConflictingKeys(slot);
} else {
slot++;
}
}
return before - size();
}
@Override
public int removeAll(ObjectPredicate<? super KType> predicate) {
final int before = size();
if (hasEmptyKey) {
if (predicate.apply(null)) {
hasEmptyKey = false;
values[mask + 1] = ((char) 0);
}
}
final KType[] keys = (KType[]) this.keys;
for (int slot = 0, max = this.mask; slot <= max;) {
KType existing;
if (!((existing = keys[slot]) == null) &&
predicate.apply(existing)) {
shiftConflictingKeys(slot);
} else {
slot++;
}
}
return before - size();
}
@Override
public char get(KType key) {
if (((key) == null)) {
return hasEmptyKey ? values[mask + 1] : ((char) 0);
} else {
final KType[] keys = (KType[]) this.keys;
final int mask = this.mask;
int slot = hashKey(key) & mask;
KType existing;
while (!((existing = keys[slot]) == null)) {
if (this.equals(existing, key)) {
return values[slot];
}
slot = (slot + 1) & mask;
}
return ((char) 0);
}
}
@Override
public char getOrDefault(KType key, char defaultValue) {
if (((key) == null)) {
return hasEmptyKey ? values[mask + 1] : defaultValue;
} else {
final KType[] keys = (KType[]) this.keys;
final int mask = this.mask;
int slot = hashKey(key) & mask;
KType existing;
while (!((existing = keys[slot]) == null)) {
if (this.equals(existing, key)) {
return values[slot];
}
slot = (slot + 1) & mask;
}
return defaultValue;
}
}
@Override
public boolean containsKey(KType key) {
if (((key) == null)) {
return hasEmptyKey;
} else {
final KType[] keys = (KType[]) this.keys;
final int mask = this.mask;
int slot = hashKey(key) & mask;
KType existing;
while (!((existing = keys[slot]) == null)) {
if (this.equals(existing, key)) {
return true;
}
slot = (slot + 1) & mask;
}
return false;
}
}
@Override
public int indexOf(KType key) {
final int mask = this.mask;
if (((key) == null)) {
return hasEmptyKey ? mask + 1 : ~(mask + 1);
} else {
final KType[] keys = (KType[]) this.keys;
int slot = hashKey(key) & mask;
KType existing;
while (!((existing = keys[slot]) == null)) {
if (this.equals(existing, key)) {
return slot;
}
slot = (slot + 1) & mask;
}
return ~slot;
}
}
@Override
public boolean indexExists(int index) {
assert index < 0 ||
(index >= 0 && index <= mask) ||
(index == mask + 1 && hasEmptyKey);
return index >= 0;
}
@Override
public char indexGet(int index) {
assert index >= 0 : "The index must point at an existing key.";
assert index <= mask ||
(index == mask + 1 && hasEmptyKey);
return values[index];
}
@Override
public char indexReplace(int index, char newValue) {
assert index >= 0 : "The index must point at an existing key.";
assert index <= mask ||
(index == mask + 1 && hasEmptyKey);
char previousValue = values[index];
values[index] = newValue;
return previousValue;
}
@Override
public void indexInsert(int index, KType key, char value) {
assert index < 0 : "The index must not point at an existing key.";
index = ~index;
if (((key) == null)) {
assert index == mask + 1;
values[index] = value;
hasEmptyKey = true;
} else {
assert ((keys[index]) == null);
if (assigned == resizeAt) {
allocateThenInsertThenRehash(index, key, value);
} else {
keys[index] = key;
values[index] = value;
}
assigned++;
}
}
@Override
public void clear() {
assigned = 0;
hasEmptyKey = false;
Arrays.fill(keys, null);
}
@Override
public void release() {
assigned = 0;
hasEmptyKey = false;
keys = null;
values = null;
ensureCapacity(Containers.DEFAULT_EXPECTED_ELEMENTS);
}
@Override
public int size() {
return assigned + (hasEmptyKey ? 1 : 0);
}
public boolean isEmpty() {
return size() == 0;
}
@Override
public int hashCode() {
int h = hasEmptyKey ? 0xDEADBEEF : 0;
for (ObjectCharCursor<KType> c : this) {
h += BitMixer.mix(c.key) +
BitMixer.mix(c.value);
}
return h;
}
@Override
public boolean equals(Object obj) {
return obj != null &&
getClass() == obj.getClass() &&
equalElements(getClass().cast(obj));
}
protected boolean equalElements(ObjectCharHashMap<?> other) {
if (other.size() != size()) {
return false;
}
for (ObjectCharCursor<?> c : other) {
KType key = (KType) c.key;
if (!containsKey(key) ||
!((get(key)) == (c.value))) {
return false;
}
}
return true;
}
@Override
public void ensureCapacity(int expectedElements) {
if (expectedElements > resizeAt || keys == null) {
final KType[] prevKeys = (KType[]) this.keys;
final char[] prevValues = this.values;
allocateBuffers(minBufferSize(expectedElements, loadFactor));
if (prevKeys != null && !isEmpty()) {
rehash(prevKeys, prevValues);
}
}
}
private final class EntryIterator extends AbstractIterator<ObjectCharCursor<KType>> {
private final ObjectCharCursor<KType> cursor;
private final int max = mask + 1;
private int slot = -1;
public EntryIterator() {
cursor = new ObjectCharCursor<KType>();
}
@Override
protected ObjectCharCursor<KType> fetch() {
if (slot < max) {
KType existing;
for (slot++; slot < max; slot++) {
if (!((existing = (KType) keys[slot]) == null)) {
cursor.index = slot;
cursor.key = existing;
cursor.value = values[slot];
return cursor;
}
}
}
if (slot == max && hasEmptyKey) {
cursor.index = slot;
cursor.key = null;
cursor.value = values[max];
slot++;
return cursor;
}
return done();
}
}
@Override
public Iterator<ObjectCharCursor<KType>> iterator() {
return new EntryIterator();
}
@Override
public <T extends ObjectCharProcedure<? super KType>> T forEach(T procedure) {
final KType[] keys = (KType[]) this.keys;
final char[] values = this.values;
if (hasEmptyKey) {
procedure.apply(null, values[mask + 1]);
}
for (int slot = 0, max = this.mask; slot <= max; slot++) {
if (!((keys[slot]) == null)) {
procedure.apply(keys[slot], values[slot]);
}
}
return procedure;
}
@Override
public <T extends ObjectCharPredicate<? super KType>> T forEach(T predicate) {
final KType[] keys = (KType[]) this.keys;
final char[] values = this.values;
if (hasEmptyKey) {
if (!predicate.apply(null, values[mask + 1])) {
return predicate;
}
}
for (int slot = 0, max = this.mask; slot <= max; slot++) {
if (!((keys[slot]) == null)) {
if (!predicate.apply(keys[slot], values[slot])) {
break;
}
}
}
return predicate;
}
public KeysContainer keys() {
return new KeysContainer();
}
public final class KeysContainer extends AbstractObjectCollection<KType>
implements ObjectLookupContainer<KType> {
private final ObjectCharHashMap<KType> owner = ObjectCharHashMap.this;
@Override
public boolean contains(KType e) {
return owner.containsKey(e);
}
@Override
public <T extends ObjectProcedure<? super KType>> T forEach(final T procedure) {
owner.forEach(new ObjectCharProcedure<KType>() {
@Override
public void apply(KType key, char value) {
procedure.apply(key);
}
});
return procedure;
}
@Override
public <T extends ObjectPredicate<? super KType>> T forEach(final T predicate) {
owner.forEach(new ObjectCharPredicate<KType>() {
@Override
public boolean apply(KType key, char value) {
return predicate.apply(key);
}
});
return predicate;
}
@Override
public boolean isEmpty() {
return owner.isEmpty();
}
@Override
public Iterator<ObjectCursor<KType>> iterator() {
return new KeysIterator();
}
@Override
public int size() {
return owner.size();
}
@Override
public void clear() {
owner.clear();
}
@Override
public void release() {
owner.release();
}
@Override
public int removeAll(ObjectPredicate<? super KType> predicate) {
return owner.removeAll(predicate);
}
@Override
public int removeAll(final KType e) {
final boolean hasKey = owner.containsKey(e);
if (hasKey) {
owner.remove(e);
return 1;
} else {
return 0;
}
}
};
private final class KeysIterator extends AbstractIterator<ObjectCursor<KType>> {
private final ObjectCursor<KType> cursor;
private final int max = mask + 1;
private int slot = -1;
public KeysIterator() {
cursor = new ObjectCursor<KType>();
}
@Override
protected ObjectCursor<KType> fetch() {
if (slot < max) {
KType existing;
for (slot++; slot < max; slot++) {
if (!((existing = (KType) keys[slot]) == null)) {
cursor.index = slot;
cursor.value = existing;
return cursor;
}
}
}
if (slot == max && hasEmptyKey) {
cursor.index = slot;
cursor.value = null;
slot++;
return cursor;
}
return done();
}
}
@Override
public CharCollection values() {
return new ValuesContainer();
}
private final class ValuesContainer extends AbstractCharCollection {
private final ObjectCharHashMap<KType> owner = ObjectCharHashMap.this;
@Override
public int size() {
return owner.size();
}
@Override
public boolean isEmpty() {
return owner.isEmpty();
}
@Override
public boolean contains(char value) {
for (ObjectCharCursor<KType> c : owner) {
if (((c.value) == (value))) {
return true;
}
}
return false;
}
@Override
public <T extends CharProcedure> T forEach(T procedure) {
for (ObjectCharCursor<KType> c : owner) {
procedure.apply(c.value);
}
return procedure;
}
@Override
public <T extends CharPredicate> T forEach(T predicate) {
for (ObjectCharCursor<KType> c : owner) {
if (!predicate.apply(c.value)) {
break;
}
}
return predicate;
}
@Override
public Iterator<CharCursor> iterator() {
return new ValuesIterator();
}
@Override
public int removeAll(final char e) {
return owner.removeAll(new ObjectCharPredicate<KType>() {
@Override
public boolean apply(KType key, char value) {
return ((value) == (e));
}
});
}
@Override
public int removeAll(final CharPredicate predicate) {
return owner.removeAll(new ObjectCharPredicate<KType>() {
@Override
public boolean apply(KType key, char value) {
return predicate.apply(value);
}
});
}
@Override
public void clear() {
owner.clear();
}
@Override
public void release() {
owner.release();
}
}
private final class ValuesIterator extends AbstractIterator<CharCursor> {
private final CharCursor cursor;
private final int max = mask + 1;
private int slot = -1;
public ValuesIterator() {
cursor = new CharCursor();
}
@Override
protected CharCursor fetch() {
if (slot < max) {
for (slot++; slot < max; slot++) {
if (!(((KType) keys[slot]) == null)) {
cursor.index = slot;
cursor.value = values[slot];
return cursor;
}
}
}
if (slot == max && hasEmptyKey) {
cursor.index = slot;
cursor.value = values[max];
slot++;
return cursor;
}
return done();
}
}
@Override
public ObjectCharHashMap<KType> clone() {
try {
ObjectCharHashMap<KType> cloned = (ObjectCharHashMap<KType>) super.clone();
cloned.keys = keys.clone();
cloned.values = values.clone();
cloned.hasEmptyKey = cloned.hasEmptyKey;
cloned.orderMixer = orderMixer.clone();
return cloned;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
@Override
public String toString() {
final StringBuilder buffer = new StringBuilder();
buffer.append("[");
boolean first = true;
for (ObjectCharCursor<KType> cursor : this) {
if (!first) {
buffer.append(", ");
}
buffer.append(cursor.key);
buffer.append("=>");
buffer.append(cursor.value);
first = false;
}
buffer.append("]");
return buffer.toString();
}
@Override
public String visualizeKeyDistribution(int characters) {
return ObjectBufferVisualizer.visualizeKeyDistribution(keys, mask, characters);
}
public static <KType> ObjectCharHashMap<KType> from(KType[] keys, char[] values) {
if (keys.length != values.length) {
throw new IllegalArgumentException("Arrays of keys and values must have an identical length.");
}
ObjectCharHashMap<KType> map = new ObjectCharHashMap<>(keys.length);
for (int i = 0; i < keys.length; i++) {
map.put(keys[i], values[i]);
}
return map;
}
protected
int hashKey(KType key) {
assert !((key) == null);
return BitMixer.mix(key, this.keyMixer);
}
protected double verifyLoadFactor(double loadFactor) {
checkLoadFactor(loadFactor, MIN_LOAD_FACTOR, MAX_LOAD_FACTOR);
return loadFactor;
}
protected void rehash(KType[] fromKeys, char[] fromValues) {
assert fromKeys.length == fromValues.length &&
HashContainers.checkPowerOfTwo(fromKeys.length - 1);
final KType[] keys = (KType[]) this.keys;
final char[] values = this.values;
final int mask = this.mask;
KType existing;
int from = fromKeys.length - 1;
keys[keys.length - 1] = fromKeys[from];
values[values.length - 1] = fromValues[from];
while (--from >= 0) {
if (!((existing = fromKeys[from]) == null)) {
int slot = hashKey(existing) & mask;
while (!((keys[slot]) == null)) {
slot = (slot + 1) & mask;
}
keys[slot] = existing;
values[slot] = fromValues[from];
}
}
}
protected void allocateBuffers(int arraySize) {
assert Integer.bitCount(arraySize) == 1;
final int newKeyMixer = this.orderMixer.newKeyMixer(arraySize);
KType[] prevKeys = (KType[]) this.keys;
char[] prevValues = this.values;
try {
int emptyElementSlot = 1;
this.keys = ((KType[]) new Object [arraySize + emptyElementSlot]);
this.values = (new char [arraySize + emptyElementSlot]);
} catch (OutOfMemoryError e) {
this.keys = prevKeys;
this.values = prevValues;
throw new BufferAllocationException(
"Not enough memory to allocate buffers for rehashing: %,d -> %,d",
e,
this.mask + 1,
arraySize);
}
this.resizeAt = expandAtCount(arraySize, loadFactor);
this.keyMixer = newKeyMixer;
this.mask = arraySize - 1;
}
protected void allocateThenInsertThenRehash(int slot, KType pendingKey, char pendingValue) {
assert assigned == resizeAt
&& (((KType) keys[slot]) == null)
&& !((pendingKey) == null);
final KType[] prevKeys = (KType[]) this.keys;
final char[] prevValues = this.values;
allocateBuffers(nextBufferSize(mask + 1, size(), loadFactor));
assert this.keys.length > prevKeys.length;
prevKeys[slot] = pendingKey;
prevValues[slot] = pendingValue;
rehash(prevKeys, prevValues);
}
protected void shiftConflictingKeys(int gapSlot) {
final KType[] keys = (KType[]) this.keys;
final char[] values = this.values;
final int mask = this.mask;
int distance = 0;
while (true) {
final int slot = (gapSlot + (++distance)) & mask;
final KType existing = keys[slot];
if (((existing) == null)) {
break;
}
final int idealSlot = hashKey(existing);
final int shift = (slot - idealSlot) & mask;
if (shift >= distance) {
keys[gapSlot] = existing;
values[gapSlot] = values[slot];
gapSlot = slot;
distance = 0;
}
}
keys[gapSlot] = null;
values[gapSlot] = ((char) 0);
assigned--;
}
protected boolean equals(Object v1, Object v2) {
return (v1 == v2) || (v1 != null && v1.equals(v2));
}
}