delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public Integer get (K key) {
+ return delegate.get(key);
+ }
+
+ @Override
+ public Integer put (K key, Integer value) {
+ return delegate.put(key, value);
+ }
+
+ @Override
+ public void clear () {
+ delegate.clear();
+ }
+ }
+
+}
diff --git a/src/com/esotericsoftware/kryo/util/IdentityMap.java b/src/com/esotericsoftware/kryo/util/IdentityMap.java
index e39bd28b0..a42af1409 100644
--- a/src/com/esotericsoftware/kryo/util/IdentityMap.java
+++ b/src/com/esotericsoftware/kryo/util/IdentityMap.java
@@ -23,15 +23,13 @@
* when growing the table size.
*
* This class performs fast contains and remove (typically O(1), worst case O(n) but that is rare in practice). Add may be
- * slightly slower, depending on hash collisions. Hashcodes are rehashed to reduce collisions and the need to resize. Load factors
- * greater than 0.91 greatly increase the chances to resize to the next higher POT size.
+ * slightly slower, depending on hash collisions. Load factors greater than 0.91 greatly increase the chances to resize to the
+ * next higher POT size.
*
* Unordered sets and maps are not designed to provide especially fast iteration.
*
- * This implementation uses linear probing with the backward shift algorithm for removal. Hashcodes are rehashed using Fibonacci
- * hashing, instead of the more common power-of-two mask, to better distribute poor hashCodes (see Malte
- * Skarupke's blog post). Linear probing continues to work even when all hashCodes collide, just more slowly.
+ * This implementation uses linear probing with the backward shift algorithm for removal. Linear probing continues to work even
+ * when all hashCodes collide, just more slowly.
* @author Tommy Ettinger
* @author Nathan Sweet */
public class IdentityMap extends ObjectMap {
@@ -59,7 +57,23 @@ public IdentityMap (IdentityMap map) {
}
protected int place (K item) {
- return (int)(System.identityHashCode(item) * 0x9E3779B97F4A7C15L >>> shift);
+ return System.identityHashCode(item) & mask;
+ }
+
+ public V get (T key) {
+ for (int i = place(key);; i = i + 1 & mask) {
+ K other = keyTable[i];
+ if (other == null) return null;
+ if (other == key) return valueTable[i];
+ }
+ }
+
+ public V get (K key, V defaultValue) {
+ for (int i = place(key);; i = i + 1 & mask) {
+ K other = keyTable[i];
+ if (other == null) return defaultValue;
+ if (other == key) return valueTable[i];
+ }
}
int locateKey (K key) {
diff --git a/src/com/esotericsoftware/kryo/util/IdentityObjectIntMap.java b/src/com/esotericsoftware/kryo/util/IdentityObjectIntMap.java
index b84cb7891..cef9b85a6 100644
--- a/src/com/esotericsoftware/kryo/util/IdentityObjectIntMap.java
+++ b/src/com/esotericsoftware/kryo/util/IdentityObjectIntMap.java
@@ -23,15 +23,13 @@
* allowed. No allocation is done except when growing the table size.
*
* This class performs fast contains and remove (typically O(1), worst case O(n) but that is rare in practice). Add may be
- * slightly slower, depending on hash collisions. Hashcodes are rehashed to reduce collisions and the need to resize. Load factors
- * greater than 0.91 greatly increase the chances to resize to the next higher POT size.
+ * slightly slower, depending on hash collisions. Load factors greater than 0.91 greatly increase the chances to resize to the
+ * next higher POT size.
*
* Unordered sets and maps are not designed to provide especially fast iteration.
*
- * This implementation uses linear probing with the backward shift algorithm for removal. Hashcodes are rehashed using Fibonacci
- * hashing, instead of the more common power-of-two mask, to better distribute poor hashCodes (see Malte
- * Skarupke's blog post). Linear probing continues to work even when all hashCodes collide, just more slowly.
+ * This implementation uses linear probing with the backward shift algorithm for removal. Linear probing continues to work even
+ * when all hashCodes collide, just more slowly.
* @author Nathan Sweet
* @author Tommy Ettinger */
public class IdentityObjectIntMap extends ObjectIntMap {
@@ -59,7 +57,15 @@ public IdentityObjectIntMap (IdentityObjectIntMap map) {
}
protected int place (K item) {
- return (int)(System.identityHashCode(item) * 0x9E3779B97F4A7C15L >>> shift);
+ return System.identityHashCode(item) & mask;
+ }
+
+ public int get (K key, int defaultValue) {
+ for (int i = place(key);; i = i + 1 & mask) {
+ K other = keyTable[i];
+ if (other == null) return defaultValue;
+ if (other == key) return valueTable[i];
+ }
}
int locateKey (K key) {
diff --git a/src/com/esotericsoftware/kryo/util/IntMap.java b/src/com/esotericsoftware/kryo/util/IntMap.java
index 438807181..df21676a3 100644
--- a/src/com/esotericsoftware/kryo/util/IntMap.java
+++ b/src/com/esotericsoftware/kryo/util/IntMap.java
@@ -187,14 +187,20 @@ private void putResize (int key, @Null V value) {
public V get (int key) {
if (key == 0) return hasZeroValue ? zeroValue : null;
- int i = locateKey(key);
- return i >= 0 ? valueTable[i] : null;
+ for (int i = place(key);; i = i + 1 & mask) {
+ int other = keyTable[i];
+ if (other == 0) return null;
+ if (other == key) return valueTable[i];
+ }
}
public V get (int key, @Null V defaultValue) {
- if (key == 0) return hasZeroValue ? zeroValue : defaultValue;
- int i = locateKey(key);
- return i >= 0 ? valueTable[i] : defaultValue;
+ if (key == 0) return hasZeroValue ? zeroValue : null;
+ for (int i = place(key);; i = i + 1 & mask) {
+ int other = keyTable[i];
+ if (other == 0) return defaultValue;
+ if (other == key) return valueTable[i];
+ }
}
@Null
diff --git a/src/com/esotericsoftware/kryo/util/ObjectIntMap.java b/src/com/esotericsoftware/kryo/util/ObjectIntMap.java
index 9ce0a49fb..8b5331df0 100644
--- a/src/com/esotericsoftware/kryo/util/ObjectIntMap.java
+++ b/src/com/esotericsoftware/kryo/util/ObjectIntMap.java
@@ -65,7 +65,7 @@ public class ObjectIntMap implements Iterable> {
protected int shift;
/** A bitmask used to confine hashcodes to the size of the table. Must be all 1 bits in its low positions, ie a power of two
- * minus 1. If {@link #place(Object)} is overriden, this can be used instead of {@link #shift} to isolate usable bits of a
+ * minus 1. If {@link #place(Object)} is overridden, this can be used instead of {@link #shift} to isolate usable bits of a
* hash. */
protected int mask;
diff --git a/src/com/esotericsoftware/kryo/util/ObjectMap.java b/src/com/esotericsoftware/kryo/util/ObjectMap.java
index e63ef10bb..471e863bb 100644
--- a/src/com/esotericsoftware/kryo/util/ObjectMap.java
+++ b/src/com/esotericsoftware/kryo/util/ObjectMap.java
@@ -62,7 +62,7 @@ public class ObjectMap implements Iterable> {
protected int shift;
/** A bitmask used to confine hashcodes to the size of the table. Must be all 1 bits in its low positions, ie a power of two
- * minus 1. If {@link #place(Object)} is overriden, this can be used instead of {@link #shift} to isolate usable bits of a
+ * minus 1. If {@link #place(Object)} is overridden, this can be used instead of {@link #shift} to isolate usable bits of a
* hash. */
protected int mask;
@@ -113,7 +113,7 @@ public ObjectMap (ObjectMap extends K, ? extends V> map) {
* "https://probablydance.com/2018/06/16/fibonacci-hashing-the-optimization-that-the-world-forgot-or-a-better-alternative-to-integer-modulo/">Malte
* Skarupke's blog post).
*
- * This method can be overriden to customizing hashing. This may be useful eg in the unlikely event that most hashcodes are
+ * This method can be overridden to customizing hashing. This may be useful eg in the unlikely event that most hashcodes are
* Fibonacci numbers, if keys provide poor or incorrect hashcodes, or to simplify hashing if keys provide high quality
* hashcodes and don't need Fibonacci hashing: {@code return item.hashCode() & mask;} */
protected int place (K item) {
@@ -121,7 +121,7 @@ protected int place (K item) {
}
/** Returns the index of the key if already present, else -(index + 1) for the next empty index. This can be overridden in this
- * pacakge to compare for equality differently than {@link Object#equals(Object)}. */
+ * package to compare for equality differently than {@link Object#equals(Object)}. */
int locateKey (K key) {
if (key == null) throw new IllegalArgumentException("key cannot be null.");
K[] keyTable = this.keyTable;
@@ -174,14 +174,20 @@ private void putResize (K key, @Null V value) {
/** Returns the value for the specified key, or null if the key is not in the map. */
@Null
public V get (T key) {
- int i = locateKey(key);
- return i < 0 ? null : valueTable[i];
+ for (int i = place(key);; i = i + 1 & mask) {
+ K other = keyTable[i];
+ if (other == null) return null;
+ if (other.equals(key)) return valueTable[i];
+ }
}
/** Returns the value for the specified key, or the default value if the key is not in the map. */
public V get (K key, @Null V defaultValue) {
- int i = locateKey(key);
- return i < 0 ? defaultValue : valueTable[i];
+ for (int i = place(key);; i = i + 1 & mask) {
+ K other = keyTable[i];
+ if (other == null) return defaultValue;
+ if (other.equals(key)) return valueTable[i];
+ }
}
@Null