2014-11-14 6 views
7

Java doc says - Quando il numero di voci nella tabella hash supera il prodotto del fattore di carico e la capacità di corrente, la tabella hash è rehashedHashMap capacità non aumentata ancora al raggiungimento soglia

Nel seguente programma -

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

chiave è di tipo intero, all'atto dell'inserimento del 13 al 15 capacità elemento HashMap rimane come 16 e la soglia rimane uguale a 12, perché?

Debug screenshot dopo l'aggiunta dell'elemento 13 ° in mappa -

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 con chiave di tipo String - HashMap<String, String> o una classe personalizzata - Map<Employee,Integer> spettacolo comportamento previsto al 13 inserimento

+3

Leggi il codice. Questo lo spiegherà. È possibile che qualcosa sia cambiato nell'implementazione, il che significa che javadoc non è più * esattamente * corretto. Ma questo non è interessante (IMO) perché nessun programmatore sensibile potrebbe mai dipendere dal comportamento preciso del ridimensionamento dell'hashmap. –

+1

Sto solo cercando di capire perché il comportamento dell'implementazione è diverso per avere chiavi come Integer. Se provo HashMap ridimensiona la mappa al 13 ° inserimento – anmolmore

+0

Quale versione di Java (incluso aggiornamento)? – m3th0dman

risposta

5

Sembra che questo comportamento è dovuto modificare l'implementazione interna del metodo Pash di HashMap nella recente versione di Java 7. Dopo aver esaminato il codice sorgente di più versioni, ho trovato una risposta alla mia domanda

HashMa Metodo p put chiama addEntry() per aggiungere una nuova voce -

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 metodo sembra -

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); 
} 

Codice sorgente di versione 1.7.0_67-b01 sembra -

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); 
} 

Quindi, nelle versioni recenti di Java, HashMap potrebbe non essere ridimensionato in base alla sola soglia. Se secchio è vuoto ingresso sarebbe ancora andare in senza ridimensionamento HashMap

Java 8 può avere un comportamento diverso, source code of version 8-b132 mostra PUT è completamente ri implementato -

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 non può essere aggiornato frequentemente come le versioni di Java! Grazie Stephen

Problemi correlati