982 lines
29 KiB
Java
982 lines
29 KiB
Java
package com.esotericsoftware.kryo.util;
|
|
|
|
import c.d.b.a.a;
|
|
import java.util.ArrayList;
|
|
import java.util.Iterator;
|
|
import java.util.NoSuchElementException;
|
|
public class IdentityMap<K, V> {
|
|
private static final int PRIME2 = -1105259343;
|
|
private static final int PRIME3 = -1262997959;
|
|
private static final int PRIME4 = -825114047;
|
|
public int capacity;
|
|
private Entries entries;
|
|
private int hashShift;
|
|
private boolean isBigTable;
|
|
public K[] keyTable;
|
|
private Keys keys;
|
|
private float loadFactor;
|
|
private int mask;
|
|
private int pushIterations;
|
|
public int size;
|
|
private int stashCapacity;
|
|
public int stashSize;
|
|
private int threshold;
|
|
public V[] valueTable;
|
|
private Values values;
|
|
|
|
public static class Entries<K, V> extends MapIterator<K, V> implements Iterable<Entry<K, V>>, Iterator<Entry<K, V>> {
|
|
private Entry<K, V> entry = new Entry<>();
|
|
|
|
public Entries(IdentityMap<K, V> identityMap) {
|
|
super(identityMap);
|
|
}
|
|
|
|
@Override // java.util.Iterator
|
|
public boolean hasNext() {
|
|
return this.hasNext;
|
|
}
|
|
|
|
@Override // java.lang.Iterable
|
|
public Iterator<Entry<K, V>> iterator() {
|
|
return this;
|
|
}
|
|
|
|
@Override // java.util.Iterator
|
|
public Entry<K, V> next() {
|
|
if (this.hasNext) {
|
|
IdentityMap<K, V> identityMap = this.map;
|
|
K[] kArr = identityMap.keyTable;
|
|
Entry<K, V> entry = this.entry;
|
|
int i = this.nextIndex;
|
|
entry.key = kArr[i];
|
|
entry.value = identityMap.valueTable[i];
|
|
this.currentIndex = i;
|
|
findNextIndex();
|
|
return this.entry;
|
|
}
|
|
throw new NoSuchElementException();
|
|
}
|
|
|
|
@Override // com.esotericsoftware.kryo.util.IdentityMap.MapIterator, java.util.Iterator
|
|
public /* bridge */ /* synthetic */ void remove() {
|
|
super.remove();
|
|
}
|
|
|
|
@Override // com.esotericsoftware.kryo.util.IdentityMap.MapIterator
|
|
public /* bridge */ /* synthetic */ void reset() {
|
|
super.reset();
|
|
}
|
|
}
|
|
|
|
public static class Entry<K, V> {
|
|
public K key;
|
|
public V value;
|
|
|
|
public String toString() {
|
|
return ((Object) this.key) + "=" + ((Object) this.value);
|
|
}
|
|
}
|
|
|
|
public static class Keys<K> extends MapIterator<K, Object> implements Iterable<K>, Iterator<K> {
|
|
public Keys(IdentityMap<K, ?> identityMap) {
|
|
super(identityMap);
|
|
}
|
|
|
|
@Override // java.util.Iterator
|
|
public boolean hasNext() {
|
|
return this.hasNext;
|
|
}
|
|
|
|
@Override // java.lang.Iterable
|
|
public Iterator<K> iterator() {
|
|
return this;
|
|
}
|
|
|
|
@Override // java.util.Iterator
|
|
public K next() {
|
|
K[] kArr = this.map.keyTable;
|
|
int i = this.nextIndex;
|
|
K k = kArr[i];
|
|
this.currentIndex = i;
|
|
findNextIndex();
|
|
return k;
|
|
}
|
|
|
|
@Override // com.esotericsoftware.kryo.util.IdentityMap.MapIterator, java.util.Iterator
|
|
public /* bridge */ /* synthetic */ void remove() {
|
|
super.remove();
|
|
}
|
|
|
|
@Override // com.esotericsoftware.kryo.util.IdentityMap.MapIterator
|
|
public /* bridge */ /* synthetic */ void reset() {
|
|
super.reset();
|
|
}
|
|
|
|
public ArrayList<K> toArray() {
|
|
ArrayList<K> arrayList = new ArrayList<>(this.map.size);
|
|
while (this.hasNext) {
|
|
arrayList.add(next());
|
|
}
|
|
return arrayList;
|
|
}
|
|
}
|
|
|
|
public static class MapIterator<K, V> {
|
|
public int currentIndex;
|
|
public boolean hasNext;
|
|
public final IdentityMap<K, V> map;
|
|
public int nextIndex;
|
|
|
|
public MapIterator(IdentityMap<K, V> identityMap) {
|
|
this.map = identityMap;
|
|
reset();
|
|
}
|
|
|
|
public void findNextIndex() {
|
|
int i;
|
|
this.hasNext = false;
|
|
IdentityMap<K, V> identityMap = this.map;
|
|
K[] kArr = identityMap.keyTable;
|
|
int i2 = identityMap.capacity + identityMap.stashSize;
|
|
do {
|
|
i = this.nextIndex + 1;
|
|
this.nextIndex = i;
|
|
if (i >= i2) {
|
|
return;
|
|
}
|
|
} while (kArr[i] == null);
|
|
this.hasNext = true;
|
|
}
|
|
|
|
@Override // java.util.Iterator
|
|
public void remove() {
|
|
int i = this.currentIndex;
|
|
if (i >= 0) {
|
|
IdentityMap<K, V> identityMap = this.map;
|
|
if (i >= identityMap.capacity) {
|
|
identityMap.removeStashIndex(i);
|
|
this.nextIndex = this.currentIndex - 1;
|
|
findNextIndex();
|
|
} else {
|
|
identityMap.keyTable[i] = null;
|
|
identityMap.valueTable[i] = null;
|
|
}
|
|
this.currentIndex = -1;
|
|
IdentityMap<K, V> identityMap2 = this.map;
|
|
identityMap2.size--;
|
|
return;
|
|
}
|
|
throw new IllegalStateException("next must be called before remove.");
|
|
}
|
|
|
|
public void reset() {
|
|
this.currentIndex = -1;
|
|
this.nextIndex = -1;
|
|
findNextIndex();
|
|
}
|
|
}
|
|
|
|
public static class Values<V> extends MapIterator<Object, V> implements Iterable<V>, Iterator<V> {
|
|
public Values(IdentityMap<?, V> identityMap) {
|
|
super(identityMap);
|
|
}
|
|
|
|
@Override // java.util.Iterator
|
|
public boolean hasNext() {
|
|
return this.hasNext;
|
|
}
|
|
|
|
@Override // java.lang.Iterable
|
|
public Iterator<V> iterator() {
|
|
return this;
|
|
}
|
|
|
|
@Override // java.util.Iterator
|
|
public V next() {
|
|
V[] vArr = this.map.valueTable;
|
|
int i = this.nextIndex;
|
|
V v = vArr[i];
|
|
this.currentIndex = i;
|
|
findNextIndex();
|
|
return v;
|
|
}
|
|
|
|
@Override // com.esotericsoftware.kryo.util.IdentityMap.MapIterator, java.util.Iterator
|
|
public /* bridge */ /* synthetic */ void remove() {
|
|
super.remove();
|
|
}
|
|
|
|
@Override // com.esotericsoftware.kryo.util.IdentityMap.MapIterator
|
|
public /* bridge */ /* synthetic */ void reset() {
|
|
super.reset();
|
|
}
|
|
|
|
public ArrayList<V> toArray() {
|
|
ArrayList<V> arrayList = new ArrayList<>(this.map.size);
|
|
while (this.hasNext) {
|
|
arrayList.add(next());
|
|
}
|
|
return arrayList;
|
|
}
|
|
|
|
public void toArray(ArrayList<V> arrayList) {
|
|
while (this.hasNext) {
|
|
arrayList.add(next());
|
|
}
|
|
}
|
|
}
|
|
|
|
public IdentityMap() {
|
|
this(32, 0.8f);
|
|
}
|
|
|
|
public IdentityMap(int i) {
|
|
this(i, 0.8f);
|
|
}
|
|
|
|
public IdentityMap(int i, float f) {
|
|
if (i < 0) {
|
|
throw new IllegalArgumentException(a.k("initialCapacity must be >= 0: ", i));
|
|
} else if (i <= 1073741824) {
|
|
int nextPowerOfTwo = ObjectMap.nextPowerOfTwo(i);
|
|
this.capacity = nextPowerOfTwo;
|
|
if (f > 0.0f) {
|
|
this.loadFactor = f;
|
|
this.isBigTable = (nextPowerOfTwo >>> 16) != 0;
|
|
this.threshold = (int) (((float) nextPowerOfTwo) * f);
|
|
this.mask = nextPowerOfTwo - 1;
|
|
this.hashShift = 31 - Integer.numberOfTrailingZeros(nextPowerOfTwo);
|
|
this.stashCapacity = Math.max(3, ((int) Math.ceil(Math.log((double) this.capacity))) * 2);
|
|
this.pushIterations = Math.max(Math.min(this.capacity, 8), ((int) Math.sqrt((double) this.capacity)) / 8);
|
|
K[] kArr = (K[]) new Object[(this.capacity + this.stashCapacity)];
|
|
this.keyTable = kArr;
|
|
this.valueTable = (V[]) new Object[kArr.length];
|
|
return;
|
|
}
|
|
throw new IllegalArgumentException("loadFactor must be > 0: " + f);
|
|
} else {
|
|
throw new IllegalArgumentException(a.k("initialCapacity is too large: ", i));
|
|
}
|
|
}
|
|
|
|
private boolean containsKeyStash(K k) {
|
|
K[] kArr = this.keyTable;
|
|
int i = this.capacity;
|
|
int i2 = this.stashSize + i;
|
|
while (i < i2) {
|
|
if (kArr[i] == k) {
|
|
return true;
|
|
}
|
|
i++;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private V getStash(K k, V v) {
|
|
K[] kArr = this.keyTable;
|
|
int i = this.capacity;
|
|
int i2 = this.stashSize + i;
|
|
while (i < i2) {
|
|
if (kArr[i] == k) {
|
|
return this.valueTable[i];
|
|
}
|
|
i++;
|
|
}
|
|
return v;
|
|
}
|
|
|
|
private int hash2(int i) {
|
|
int i2 = i * -1105259343;
|
|
return (i2 ^ (i2 >>> this.hashShift)) & this.mask;
|
|
}
|
|
|
|
private int hash3(int i) {
|
|
int i2 = i * -1262997959;
|
|
return (i2 ^ (i2 >>> this.hashShift)) & this.mask;
|
|
}
|
|
|
|
private int hash4(int i) {
|
|
int i2 = i * -825114047;
|
|
return (i2 ^ (i2 >>> this.hashShift)) & this.mask;
|
|
}
|
|
|
|
private void push(K k, V v, int i, K k2, int i2, K k3, int i3, K k4, int i4, K k5) {
|
|
K[] kArr = this.keyTable;
|
|
V[] vArr = this.valueTable;
|
|
int i5 = this.mask;
|
|
boolean z2 = this.isBigTable;
|
|
int i6 = this.pushIterations;
|
|
int i7 = z2 ? 4 : 3;
|
|
K k6 = k;
|
|
V v2 = v;
|
|
int i8 = i;
|
|
K k7 = k2;
|
|
int i9 = i2;
|
|
K k8 = k3;
|
|
int i10 = i3;
|
|
K k9 = k4;
|
|
int i11 = i4;
|
|
K k10 = k5;
|
|
int i12 = 0;
|
|
while (true) {
|
|
int nextInt = ObjectMap.random.nextInt(i7);
|
|
if (nextInt == 0) {
|
|
V v3 = vArr[i8];
|
|
kArr[i8] = k6;
|
|
vArr[i8] = v2;
|
|
k6 = k7;
|
|
v2 = v3;
|
|
} else if (nextInt == 1) {
|
|
V v4 = vArr[i9];
|
|
kArr[i9] = k6;
|
|
vArr[i9] = v2;
|
|
v2 = v4;
|
|
k6 = k8;
|
|
} else if (nextInt != 2) {
|
|
V v5 = vArr[i11];
|
|
kArr[i11] = k6;
|
|
vArr[i11] = v2;
|
|
v2 = v5;
|
|
k6 = k10;
|
|
} else {
|
|
V v6 = vArr[i10];
|
|
kArr[i10] = k6;
|
|
vArr[i10] = v2;
|
|
v2 = v6;
|
|
k6 = k9;
|
|
}
|
|
int identityHashCode = System.identityHashCode(k6);
|
|
int i13 = identityHashCode & i5;
|
|
K k11 = kArr[i13];
|
|
if (k11 == null) {
|
|
kArr[i13] = k6;
|
|
vArr[i13] = v2;
|
|
int i14 = this.size;
|
|
this.size = i14 + 1;
|
|
if (i14 >= this.threshold) {
|
|
resize(this.capacity << 1);
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
int hash2 = hash2(identityHashCode);
|
|
K k12 = kArr[hash2];
|
|
if (k12 == null) {
|
|
kArr[hash2] = k6;
|
|
vArr[hash2] = v2;
|
|
int i15 = this.size;
|
|
this.size = i15 + 1;
|
|
if (i15 >= this.threshold) {
|
|
resize(this.capacity << 1);
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
int hash3 = hash3(identityHashCode);
|
|
K k13 = kArr[hash3];
|
|
if (k13 == null) {
|
|
kArr[hash3] = k6;
|
|
vArr[hash3] = v2;
|
|
int i16 = this.size;
|
|
this.size = i16 + 1;
|
|
if (i16 >= this.threshold) {
|
|
resize(this.capacity << 1);
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
if (z2) {
|
|
int hash4 = hash4(identityHashCode);
|
|
K k14 = kArr[hash4];
|
|
if (k14 == null) {
|
|
kArr[hash4] = k6;
|
|
vArr[hash4] = v2;
|
|
int i17 = this.size;
|
|
this.size = i17 + 1;
|
|
if (i17 >= this.threshold) {
|
|
resize(this.capacity << 1);
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
k10 = k14;
|
|
i11 = hash4;
|
|
}
|
|
int i18 = i12 + 1;
|
|
if (i18 == i6) {
|
|
putStash(k6, v2);
|
|
return;
|
|
}
|
|
i12 = i18;
|
|
i8 = i13;
|
|
k7 = k11;
|
|
i9 = hash2;
|
|
k8 = k12;
|
|
i10 = hash3;
|
|
i7 = i7;
|
|
k9 = k13;
|
|
}
|
|
}
|
|
|
|
private void putResize(K k, V v) {
|
|
K k2;
|
|
int i;
|
|
int identityHashCode = System.identityHashCode(k);
|
|
int i2 = identityHashCode & this.mask;
|
|
K[] kArr = this.keyTable;
|
|
K k3 = kArr[i2];
|
|
if (k3 == null) {
|
|
kArr[i2] = k;
|
|
this.valueTable[i2] = v;
|
|
int i3 = this.size;
|
|
this.size = i3 + 1;
|
|
if (i3 >= this.threshold) {
|
|
resize(this.capacity << 1);
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
int hash2 = hash2(identityHashCode);
|
|
K[] kArr2 = this.keyTable;
|
|
K k4 = kArr2[hash2];
|
|
if (k4 == null) {
|
|
kArr2[hash2] = k;
|
|
this.valueTable[hash2] = v;
|
|
int i4 = this.size;
|
|
this.size = i4 + 1;
|
|
if (i4 >= this.threshold) {
|
|
resize(this.capacity << 1);
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
int hash3 = hash3(identityHashCode);
|
|
K[] kArr3 = this.keyTable;
|
|
K k5 = kArr3[hash3];
|
|
if (k5 == null) {
|
|
kArr3[hash3] = k;
|
|
this.valueTable[hash3] = v;
|
|
int i5 = this.size;
|
|
this.size = i5 + 1;
|
|
if (i5 >= this.threshold) {
|
|
resize(this.capacity << 1);
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
if (this.isBigTable) {
|
|
int hash4 = hash4(identityHashCode);
|
|
K[] kArr4 = this.keyTable;
|
|
K k6 = kArr4[hash4];
|
|
if (k6 == null) {
|
|
kArr4[hash4] = k;
|
|
this.valueTable[hash4] = v;
|
|
int i6 = this.size;
|
|
this.size = i6 + 1;
|
|
if (i6 >= this.threshold) {
|
|
resize(this.capacity << 1);
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
i = hash4;
|
|
k2 = k6;
|
|
} else {
|
|
k2 = null;
|
|
i = -1;
|
|
}
|
|
push(k, v, i2, k3, hash2, k4, hash3, k5, i, k2);
|
|
}
|
|
|
|
private void putStash(K k, V v) {
|
|
int i = this.stashSize;
|
|
if (i == this.stashCapacity) {
|
|
resize(this.capacity << 1);
|
|
put(k, v);
|
|
return;
|
|
}
|
|
int i2 = this.capacity + i;
|
|
this.keyTable[i2] = k;
|
|
this.valueTable[i2] = v;
|
|
this.stashSize = i + 1;
|
|
this.size++;
|
|
}
|
|
|
|
private void resize(int i) {
|
|
int i2 = this.capacity + this.stashSize;
|
|
this.capacity = i;
|
|
this.threshold = (int) (((float) i) * this.loadFactor);
|
|
this.mask = i - 1;
|
|
this.hashShift = 31 - Integer.numberOfTrailingZeros(i);
|
|
double d = (double) i;
|
|
this.stashCapacity = Math.max(3, ((int) Math.ceil(Math.log(d))) * 2);
|
|
this.pushIterations = Math.max(Math.min(i, 8), ((int) Math.sqrt(d)) / 8);
|
|
this.isBigTable = (this.capacity >>> 16) != 0;
|
|
K[] kArr = this.keyTable;
|
|
V[] vArr = this.valueTable;
|
|
int i3 = this.stashCapacity;
|
|
this.keyTable = (K[]) new Object[(i + i3)];
|
|
this.valueTable = (V[]) new Object[(i + i3)];
|
|
int i4 = this.size;
|
|
this.size = 0;
|
|
this.stashSize = 0;
|
|
if (i4 > 0) {
|
|
for (int i5 = 0; i5 < i2; i5++) {
|
|
K k = kArr[i5];
|
|
if (k != null) {
|
|
putResize(k, vArr[i5]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void clear() {
|
|
K[] kArr = this.keyTable;
|
|
V[] vArr = this.valueTable;
|
|
int i = this.capacity + this.stashSize;
|
|
while (true) {
|
|
int i2 = i - 1;
|
|
if (i > 0) {
|
|
kArr[i2] = null;
|
|
vArr[i2] = null;
|
|
i = i2;
|
|
} else {
|
|
this.size = 0;
|
|
this.stashSize = 0;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void clear(int i) {
|
|
if (this.capacity <= i) {
|
|
clear();
|
|
return;
|
|
}
|
|
this.size = 0;
|
|
resize(i);
|
|
}
|
|
|
|
public boolean containsKey(K k) {
|
|
int identityHashCode = System.identityHashCode(k);
|
|
if (k == this.keyTable[this.mask & identityHashCode]) {
|
|
return true;
|
|
}
|
|
if (k == this.keyTable[hash2(identityHashCode)]) {
|
|
return true;
|
|
}
|
|
if (k == this.keyTable[hash3(identityHashCode)]) {
|
|
return true;
|
|
}
|
|
if (!this.isBigTable) {
|
|
return containsKeyStash(k);
|
|
}
|
|
if (k != this.keyTable[hash4(identityHashCode)]) {
|
|
return containsKeyStash(k);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public boolean containsValue(Object obj, boolean z2) {
|
|
V[] vArr = this.valueTable;
|
|
if (obj == null) {
|
|
K[] kArr = this.keyTable;
|
|
int i = this.capacity + this.stashSize;
|
|
while (true) {
|
|
int i2 = i - 1;
|
|
if (i <= 0) {
|
|
return false;
|
|
}
|
|
if (kArr[i2] != null && vArr[i2] == null) {
|
|
return true;
|
|
}
|
|
i = i2;
|
|
}
|
|
} else if (z2) {
|
|
int i3 = this.capacity + this.stashSize;
|
|
while (true) {
|
|
int i4 = i3 - 1;
|
|
if (i3 <= 0) {
|
|
return false;
|
|
}
|
|
if (vArr[i4] == obj) {
|
|
return true;
|
|
}
|
|
i3 = i4;
|
|
}
|
|
} else {
|
|
int i5 = this.capacity + this.stashSize;
|
|
while (true) {
|
|
int i6 = i5 - 1;
|
|
if (i5 <= 0) {
|
|
return false;
|
|
}
|
|
if (obj.equals(vArr[i6])) {
|
|
return true;
|
|
}
|
|
i5 = i6;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void ensureCapacity(int i) {
|
|
int i2 = this.size + i;
|
|
if (i2 >= this.threshold) {
|
|
resize(ObjectMap.nextPowerOfTwo((int) (((float) i2) / this.loadFactor)));
|
|
}
|
|
}
|
|
|
|
public Entries<K, V> entries() {
|
|
Entries entries = this.entries;
|
|
if (entries == null) {
|
|
this.entries = new Entries(this);
|
|
} else {
|
|
entries.reset();
|
|
}
|
|
return this.entries;
|
|
}
|
|
|
|
public K findKey(Object obj, boolean z2) {
|
|
V[] vArr = this.valueTable;
|
|
if (obj == null) {
|
|
K[] kArr = this.keyTable;
|
|
int i = this.capacity + this.stashSize;
|
|
while (true) {
|
|
int i2 = i - 1;
|
|
if (i <= 0) {
|
|
return null;
|
|
}
|
|
if (kArr[i2] != null && vArr[i2] == null) {
|
|
return kArr[i2];
|
|
}
|
|
i = i2;
|
|
}
|
|
} else if (z2) {
|
|
int i3 = this.capacity + this.stashSize;
|
|
while (true) {
|
|
int i4 = i3 - 1;
|
|
if (i3 <= 0) {
|
|
return null;
|
|
}
|
|
if (vArr[i4] == obj) {
|
|
return this.keyTable[i4];
|
|
}
|
|
i3 = i4;
|
|
}
|
|
} else {
|
|
int i5 = this.capacity + this.stashSize;
|
|
while (true) {
|
|
int i6 = i5 - 1;
|
|
if (i5 <= 0) {
|
|
return null;
|
|
}
|
|
if (obj.equals(vArr[i6])) {
|
|
return this.keyTable[i6];
|
|
}
|
|
i5 = i6;
|
|
}
|
|
}
|
|
}
|
|
|
|
public V get(K k) {
|
|
int identityHashCode = System.identityHashCode(k);
|
|
int i = this.mask & identityHashCode;
|
|
if (k != this.keyTable[i]) {
|
|
i = hash2(identityHashCode);
|
|
if (k != this.keyTable[i]) {
|
|
i = hash3(identityHashCode);
|
|
if (k != this.keyTable[i]) {
|
|
if (!this.isBigTable) {
|
|
return getStash(k, null);
|
|
}
|
|
i = hash4(identityHashCode);
|
|
if (k != this.keyTable[i]) {
|
|
return getStash(k, null);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return this.valueTable[i];
|
|
}
|
|
|
|
public V get(K k, V v) {
|
|
int identityHashCode = System.identityHashCode(k);
|
|
int i = this.mask & identityHashCode;
|
|
if (k != this.keyTable[i]) {
|
|
i = hash2(identityHashCode);
|
|
if (k != this.keyTable[i]) {
|
|
i = hash3(identityHashCode);
|
|
if (k != this.keyTable[i]) {
|
|
if (!this.isBigTable) {
|
|
return getStash(k, v);
|
|
}
|
|
i = hash4(identityHashCode);
|
|
if (k != this.keyTable[i]) {
|
|
return getStash(k, v);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return this.valueTable[i];
|
|
}
|
|
|
|
public Keys<K> keys() {
|
|
Keys keys = this.keys;
|
|
if (keys == null) {
|
|
this.keys = new Keys(this);
|
|
} else {
|
|
keys.reset();
|
|
}
|
|
return this.keys;
|
|
}
|
|
|
|
public V put(K k, V v) {
|
|
K k2;
|
|
int i;
|
|
if (k != null) {
|
|
K[] kArr = this.keyTable;
|
|
int i2 = this.mask;
|
|
boolean z2 = this.isBigTable;
|
|
int identityHashCode = System.identityHashCode(k);
|
|
int i3 = identityHashCode & i2;
|
|
K k3 = kArr[i3];
|
|
if (k3 == k) {
|
|
V[] vArr = this.valueTable;
|
|
V v2 = vArr[i3];
|
|
vArr[i3] = v;
|
|
return v2;
|
|
}
|
|
int hash2 = hash2(identityHashCode);
|
|
K k4 = kArr[hash2];
|
|
if (k4 == k) {
|
|
V[] vArr2 = this.valueTable;
|
|
V v3 = vArr2[hash2];
|
|
vArr2[hash2] = v;
|
|
return v3;
|
|
}
|
|
int hash3 = hash3(identityHashCode);
|
|
K k5 = kArr[hash3];
|
|
if (k5 == k) {
|
|
V[] vArr3 = this.valueTable;
|
|
V v4 = vArr3[hash3];
|
|
vArr3[hash3] = v;
|
|
return v4;
|
|
}
|
|
if (z2) {
|
|
int hash4 = hash4(identityHashCode);
|
|
K k6 = kArr[hash4];
|
|
if (k6 == k) {
|
|
V[] vArr4 = this.valueTable;
|
|
V v5 = vArr4[hash4];
|
|
vArr4[hash4] = v;
|
|
return v5;
|
|
}
|
|
i = hash4;
|
|
k2 = k6;
|
|
} else {
|
|
k2 = null;
|
|
i = -1;
|
|
}
|
|
int i4 = this.capacity;
|
|
int i5 = this.stashSize + i4;
|
|
while (i4 < i5) {
|
|
if (kArr[i4] == k) {
|
|
V[] vArr5 = this.valueTable;
|
|
V v6 = vArr5[i4];
|
|
vArr5[i4] = v;
|
|
return v6;
|
|
}
|
|
i4++;
|
|
}
|
|
if (k3 == null) {
|
|
kArr[i3] = k;
|
|
this.valueTable[i3] = v;
|
|
int i6 = this.size;
|
|
this.size = i6 + 1;
|
|
if (i6 >= this.threshold) {
|
|
resize(this.capacity << 1);
|
|
}
|
|
return null;
|
|
} else if (k4 == null) {
|
|
kArr[hash2] = k;
|
|
this.valueTable[hash2] = v;
|
|
int i7 = this.size;
|
|
this.size = i7 + 1;
|
|
if (i7 >= this.threshold) {
|
|
resize(this.capacity << 1);
|
|
}
|
|
return null;
|
|
} else if (k5 == null) {
|
|
kArr[hash3] = k;
|
|
this.valueTable[hash3] = v;
|
|
int i8 = this.size;
|
|
this.size = i8 + 1;
|
|
if (i8 >= this.threshold) {
|
|
resize(this.capacity << 1);
|
|
}
|
|
return null;
|
|
} else if (!z2 || k2 != null) {
|
|
push(k, v, i3, k3, hash2, k4, hash3, k5, i, k2);
|
|
return null;
|
|
} else {
|
|
kArr[i] = k;
|
|
this.valueTable[i] = v;
|
|
int i9 = this.size;
|
|
this.size = i9 + 1;
|
|
if (i9 >= this.threshold) {
|
|
resize(this.capacity << 1);
|
|
}
|
|
return null;
|
|
}
|
|
} else {
|
|
throw new IllegalArgumentException("key cannot be null.");
|
|
}
|
|
}
|
|
|
|
public V remove(K k) {
|
|
int identityHashCode = System.identityHashCode(k);
|
|
int i = this.mask & identityHashCode;
|
|
K[] kArr = this.keyTable;
|
|
if (kArr[i] == k) {
|
|
kArr[i] = null;
|
|
V[] vArr = this.valueTable;
|
|
V v = vArr[i];
|
|
vArr[i] = null;
|
|
this.size--;
|
|
return v;
|
|
}
|
|
int hash2 = hash2(identityHashCode);
|
|
K[] kArr2 = this.keyTable;
|
|
if (kArr2[hash2] == k) {
|
|
kArr2[hash2] = null;
|
|
V[] vArr2 = this.valueTable;
|
|
V v2 = vArr2[hash2];
|
|
vArr2[hash2] = null;
|
|
this.size--;
|
|
return v2;
|
|
}
|
|
int hash3 = hash3(identityHashCode);
|
|
K[] kArr3 = this.keyTable;
|
|
if (kArr3[hash3] == k) {
|
|
kArr3[hash3] = null;
|
|
V[] vArr3 = this.valueTable;
|
|
V v3 = vArr3[hash3];
|
|
vArr3[hash3] = null;
|
|
this.size--;
|
|
return v3;
|
|
}
|
|
if (this.isBigTable) {
|
|
int hash4 = hash4(identityHashCode);
|
|
K[] kArr4 = this.keyTable;
|
|
if (kArr4[hash4] == k) {
|
|
kArr4[hash4] = null;
|
|
V[] vArr4 = this.valueTable;
|
|
V v4 = vArr4[hash4];
|
|
vArr4[hash4] = null;
|
|
this.size--;
|
|
return v4;
|
|
}
|
|
}
|
|
return removeStash(k);
|
|
}
|
|
|
|
public V removeStash(K k) {
|
|
K[] kArr = this.keyTable;
|
|
int i = this.capacity;
|
|
int i2 = this.stashSize + i;
|
|
while (i < i2) {
|
|
if (kArr[i] == k) {
|
|
V v = this.valueTable[i];
|
|
removeStashIndex(i);
|
|
this.size--;
|
|
return v;
|
|
}
|
|
i++;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public void removeStashIndex(int i) {
|
|
int i2 = this.stashSize - 1;
|
|
this.stashSize = i2;
|
|
int i3 = this.capacity + i2;
|
|
if (i < i3) {
|
|
K[] kArr = this.keyTable;
|
|
kArr[i] = kArr[i3];
|
|
V[] vArr = this.valueTable;
|
|
vArr[i] = vArr[i3];
|
|
vArr[i3] = null;
|
|
return;
|
|
}
|
|
this.valueTable[i] = null;
|
|
}
|
|
|
|
public void shrink(int i) {
|
|
if (i >= 0) {
|
|
int i2 = this.size;
|
|
if (i2 > i) {
|
|
i = i2;
|
|
}
|
|
if (this.capacity > i) {
|
|
resize(ObjectMap.nextPowerOfTwo(i));
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
throw new IllegalArgumentException(a.k("maximumCapacity must be >= 0: ", i));
|
|
}
|
|
|
|
public String toString() {
|
|
int i;
|
|
if (this.size == 0) {
|
|
return "[]";
|
|
}
|
|
StringBuilder sb = new StringBuilder(32);
|
|
sb.append('[');
|
|
K[] kArr = this.keyTable;
|
|
V[] vArr = this.valueTable;
|
|
int length = kArr.length;
|
|
while (true) {
|
|
i = length - 1;
|
|
if (length > 0) {
|
|
K k = kArr[i];
|
|
if (k != null) {
|
|
sb.append((Object) k);
|
|
sb.append('=');
|
|
sb.append((Object) vArr[i]);
|
|
break;
|
|
}
|
|
length = i;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
while (true) {
|
|
int i2 = i - 1;
|
|
if (i > 0) {
|
|
K k2 = kArr[i2];
|
|
if (k2 != null) {
|
|
sb.append(", ");
|
|
sb.append((Object) k2);
|
|
sb.append('=');
|
|
sb.append((Object) vArr[i2]);
|
|
}
|
|
i = i2;
|
|
} else {
|
|
sb.append(']');
|
|
return sb.toString();
|
|
}
|
|
}
|
|
}
|
|
|
|
public Values<V> values() {
|
|
Values values = this.values;
|
|
if (values == null) {
|
|
this.values = new Values(this);
|
|
} else {
|
|
values.reset();
|
|
}
|
|
return this.values;
|
|
}
|
|
}
|