Per dirla in modo più semplice (per quanto potrei più semplice) + alcuni dettagli in più.
Queste proprietà dipendono da molte cose interne che sarebbe molto interessante capire, prima di passare direttamente ad esse.
TREEIFY_THRESHOLD -> quando un singolo bucket raggiunge questo (e il numero totale supera MIN_TREEIFY_CAPACITY
), viene trasformato in un nodo dell'albero rosso / nero perfettamente bilanciato . Perché? A causa della velocità di ricerca. Pensaci in un modo diverso:
sarebbero necessari al massimo 32 passaggi per cercare una voce in un bucket / bin con voci Integer.MAX_VALUE .
Qualche introduzione per il prossimo argomento. Perché il numero di bidoni / secchi è sempre una potenza di due ? Almeno due ragioni: più veloce dell'operazione modulo e modulo su numeri negativi sarà negativo. E non puoi inserire una voce in un bucket "negativo":
int arrayIndex = hashCode % buckets; // will be negative
buckets[arrayIndex] = Entry; // obviously will fail
Invece c'è un bel trucco usato al posto del modulo:
(n - 1) & hash // n is the number of bins, hash - is the hash function of the key
Questo è semanticamente lo stesso dell'operazione modulo. Manterrà i bit inferiori. Ciò ha una conseguenza interessante quando fai:
Map<String, String> map = new HashMap<>();
Nel caso precedente, la decisione su dove va una voce viene presa in base agli ultimi 4 bit solo del tuo codice hash.
È qui che entra in gioco la moltiplicazione dei secchi. In determinate condizioni (occorrerebbe molto tempo per spiegarlo nei dettagli esatti ), le dimensioni dei secchi sono raddoppiate. Perché? Quando le dimensioni dei secchi sono raddoppiate, entra in gioco un altro bit .
Quindi hai 16 bucket: gli ultimi 4 bit del codice hash decidono dove va una voce. Raddoppi i bucket: 32 bucket: gli ultimi 5 bit decidono dove andrà a finire l'ingresso.
In quanto tale, questo processo è chiamato re-hashing. Questo potrebbe rallentare. Cioè (per le persone a cui importa) come HashMap è "scherzato" come: veloce, veloce, veloce, slooow . Ci sono altre implementazioni: cerca hashmap senza pausa ...
Ora UNTREEIFY_THRESHOLD entra in gioco dopo il nuovo hashing. A quel punto, alcune voci potrebbero spostarsi da questi contenitori ad altri (aggiungono un bit in più al (n-1)&hash
calcolo - e come tali potrebbero spostarsi su altri contenitori) e potrebbe raggiungere questo UNTREEIFY_THRESHOLD
. A questo punto non conviene tenere il cestino come red-black tree node
, ma come LinkedList
invece, come
entry.next.next....
MIN_TREEIFY_CAPACITY è il numero minimo di bucket prima che un determinato bucket venga trasformato in un albero.
String
, hanno uno spazio dei valori molto più grande delint
codice hash, quindi le collisioni sono inevitabili. Ora dipende dai valori effettivi, come quelli effettiviString
, inseriti nella mappa, indipendentemente dal fatto che si ottenga una distribuzione uniforme o meno. Una cattiva distribuzione può essere il risultato solo di sfortuna.