Index: src/main/java/java/util/LinkedHashMap.java =================================================================== --- src/main/java/java/util/LinkedHashMap.java (revision 610378) +++ src/main/java/java/util/LinkedHashMap.java (working copy) @@ -143,7 +143,7 @@ if (currentEntry==null) { throw new IllegalStateException(); } - associatedMap.removeEntry(currentEntry); + associatedMap.removeEntry(currentEntry.getKey()); LinkedHashMapEntry lhme = currentEntry; LinkedHashMapEntry p = lhme.chainBackward; LinkedHashMapEntry n = lhme.chainForward; Index: src/main/java/java/util/HashMap.java =================================================================== --- src/main/java/java/util/HashMap.java (revision 610378) +++ src/main/java/java/util/HashMap.java (working copy) @@ -43,18 +43,28 @@ private static final int DEFAULT_SIZE = 16; static class Entry extends MapEntry { - final int origKeyHash; + final int storedKeyHash; Entry next; Entry(K theKey, int hash) { super(theKey, null); - this.origKeyHash = hash; + if (theKey instanceof Integer) { + this.storedKeyHash = hash | 0x00000001; + } else { + this.storedKeyHash = hash & 0xFFFFFFFE; + } } Entry(K theKey, V theValue) { super(theKey, theValue); - origKeyHash = (theKey == null ? 0 : theKey.hashCode()); + if (theKey == null) { + storedKeyHash = 0; + } else if (theKey instanceof Integer) { + storedKeyHash = theKey.hashCode() | 0x00000001; + } else { + storedKeyHash = theKey.hashCode() & 0xFFFFFFFE; + } } @Override @@ -128,9 +138,16 @@ throw new IllegalStateException(); } if(prevEntry==null){ - int index = currentEntry.origKeyHash & (associatedMap.elementData.length - 1); - //assert associatedMap.elementData[index] == currentEntry; - associatedMap.elementData[index] = associatedMap.elementData[index].next; + // Since we stole the last bit to encode the type, we don't know which + // of two indices this entry came from, so try both. + int index = currentEntry.storedKeyHash & (associatedMap.elementData.length - 1); + index &= 0xFFFFFFFE; + if (associatedMap.elementData[index] == currentEntry) { + associatedMap.elementData[index] = associatedMap.elementData[index].next; + } else { + index |= 0x00000001; + associatedMap.elementData[index] = associatedMap.elementData[index].next; + } } else { prevEntry.next = currentEntry.next; } @@ -205,8 +222,8 @@ if (object instanceof Map.Entry) { Map.Entry oEntry = (Map.Entry) object; Entry entry = associatedMap.getEntry(oEntry.getKey()); - if(valuesEq(entry, oEntry)) { - associatedMap.removeEntry(entry); + if (valuesEq(entry, oEntry)) { + associatedMap.remove(oEntry.getKey()); return true; } } @@ -283,6 +300,9 @@ if(x == 0){ return 16; } + if (x == 1) { + return 2; + } x = x -1; x |= x >> 1; x |= x >> 2; @@ -467,18 +487,38 @@ return m; } - final Entry findNonNullKeyEntry(Object key, int index, int keyHash) { + final Entry findNonNullKeyEntryInteger(Object key, int index, int keyHash) { Entry m = elementData[index]; - while (m != null && (m.origKeyHash != keyHash || !key.equals(m.key))) { - m = m.next; + int storedKeyHash = keyHash | 0x00000001; + while (m != null && (m.storedKeyHash != storedKeyHash)) { + m = m.next; } return m; } + final Entry findNonNullKeyEntryLegacy(Object key, int index, int keyHash) { + Entry m = elementData[index]; + int storedKeyHash = keyHash & 0xFFFFFFFE; + while (m != null && (m.storedKeyHash != storedKeyHash || !key.equals(m.key))) { + m = m.next; + } + return m; + } + + + final Entry findNonNullKeyEntry(Object key, int index, int keyHash) { + if (key instanceof Integer) { + return findNonNullKeyEntryInteger(key, index, keyHash); + } else { + return findNonNullKeyEntryLegacy(key, index, keyHash); + } + } + final Entry findNullKeyEntry() { Entry m = elementData[0]; - while (m != null && m.key != null) + while (m != null && m.key != null) { m = m.next; + } return m; } @@ -628,7 +668,8 @@ for (int i = 0; i < elementData.length; i++) { Entry entry = elementData[i]; while (entry != null) { - int index = entry.origKeyHash & (length - 1); + int actualHash = (i & 0x00000001) | (entry.storedKeyHash & 0xFFFFFFFE); + int index = actualHash & (length - 1); Entry next = entry.next; entry.next = newData[index]; newData[index] = entry; @@ -660,33 +701,27 @@ return null; } - final void removeEntry(Entry entry) { - int index = entry.origKeyHash & (elementData.length - 1); - Entry m = elementData[index]; - if (m == entry) { - elementData[index] = entry.next; - } else { - while (m.next != entry && m.next != null) { - m = m.next; - } - m.next = entry.next; - - } - modCount++; - elementCount--; - } - final Entry removeEntry(Object key) { int index = 0; Entry entry; Entry last = null; if (key != null) { - int hash = key.hashCode(); - index = hash & (elementData.length - 1); + int keyHash = key.hashCode(); + index = keyHash & (elementData.length - 1); entry = elementData[index]; - while (entry != null && !(entry.origKeyHash == hash && key.equals(entry.key))) { - last = entry; - entry = entry.next; + + if (key instanceof Integer) { + int storedKeyHash = keyHash | 0x00000001; + while (entry != null && (entry.storedKeyHash != storedKeyHash)) { + last = entry; + entry = entry.next; + } + } else { + int storedKeyHash = keyHash & 0xFFFFFFFE; + while (entry != null && (entry.storedKeyHash != storedKeyHash || !key.equals(entry.key))) { + last = entry; + entry = entry.next; + } } } else { entry = elementData[0];