2014-11-14 4 views
7

Java doc says-Wenn die Anzahl der Einträge in der Hash-Tabelle das Produkt des Ladefaktors und die aktuellen Kapazität übersteigt, wird die Hash-Tabelle rehashedHashMap Kapazität nicht einmal erhöht auf Schwelle erreicht

Im folgende Programm -

HashMap<Integer, String> map = new HashMap<Integer, String>(); 
int i = 1; 
while(i<16) { 
    map.put(i, new Integer(i).toString()); 
    i++; 
} 

Key ist vom Typ Integer bei Einfügung 13. bis 15. Element HashMap Kapazität bleibt, wie 16 und Schwelle bleibt gleich wie 12, warum?

Debug Screenshot nach in der Karte 13.es Element hinzugefügt wird -

args     String[0] (id=16) 
map HashMap<K,V> (id=19) 
entrySet null 
hashSeed 0 
KeySet  null 
loadFactor 0.75 
modCount 13 
size  13 
table  HashMap$Entry<K,V>[16] (id=25) 
threshold 12 
values  null 
i 14 

[null, 1=1, 2=2, 3=3, 4=4, 5=5, 6=6, 7=7, 8=8, 9=9, 10=10, 11=11, 12=12, 13=13, null, null] 

HashMap mit Schlüsseln vom Typ String - HashMap<String, String> oder einem benutzerdefinierten Klasse - Map<Employee,Integer> Show erwarteten Verhalten bei 13.er Insertion

+3

Lesen Sie den Code. Das wird es erklären. Es ist möglich, dass sich bei der Implementierung etwas geändert hat, was bedeutet, dass das Javadoc nicht mehr * genau * korrekt ist. Aber das ist nicht interessant (IMO), weil kein vernünftiger Programmierer jemals auf das genaue Verhalten der hashmap-Größenänderung angewiesen wäre. –

+1

Nur zu versuchen, herauszufinden, warum das Implementierungsverhalten für Keys als Integer anders ist. Wenn ich HashMap versuche, ändert es die Größe der Map bei der 13. Einfügung. – anmolmore

+0

Welche Java-Version (einschließlich Update)? – m3th0dman

Antwort

5

aussieht wie dieses Verhalten zurückzuführen ist zu ändern in der internen Implementierung von HashMap PUT-Methode in der aktuellen Version von Java 7. Nach dem Durchlaufen des Quellcodes mehrerer Versionen, eine Antwort auf meine Frage

HashMa gefunden p Put-Methode ruft addEntry() einen neuen Eintrag hinzufügen -

public V put(K key, V value) { 
    ... 
    int hash = hash(key); 
    int i = indexFor(hash, table.length); 
    ... 
    addEntry(hash, key, value, i); 
    ... 
} 

jdk7-b147 HashMap.addEntry Methode sieht aus wie -

addEntry(int hash, K key, V value, int bucketIndex) { 
    Entry<K,V> e = table[bucketIndex]; 
    table[bucketIndex] = new Entry<>(hash, key, value, e); 
    if (size++ >= threshold) 
     resize(2 * table.length); 
} 

Quellcode der Version 1.7.0_67-b01 sieht aus wie -

void addEntry(int hash, K key, V value, int bucketIndex) { 
    if ((size >= threshold) && (null != table[bucketIndex])) { 
     resize(2 * table.length); 
     hash = (null != key) ? hash(key) : 0; 
     bucketIndex = indexFor(hash, table.length); 
    } 
    createEntry(hash, key, value, bucketIndex); 
} 

In neueren Versionen von Java wird die Größe von HashMap möglicherweise nicht nur auf der Grundlage des Schwellenwerts angepasst. Wenn Eimer leer geht in Eintrag noch wäre ohne Ändern der Größe HashMap

Java 8 unterschiedliches Verhalten haben kann, zeigt source code of version 8-b132 PUT vollständig neu implementiert wird -

put(K key, V value) { 
    return putVal(hash(key), key, value, false, true); 
} 

putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) { 
    Node<K,V>[] tab; Node<K,V> p; int n, i; 
    if ((tab = table) == null || (n = tab.length) == 0) 
    n = (tab = resize()).length; 
    .... 
} 

final Node<K,V>[] resize() { 
    //many levels of checks before resizing 
} 

Java doc nicht so häufig wie Java-Versionen aktualisiert werden kann! Danke Stephen