Hashtable, HashMap, HashSet, concetto di tabella hash in Java collection framework
Sto imparando Java Collection Framework e ho una comprensione moderata. Ora, quando sto andando un po ' oltre ho qualche dubbio in: HashMap
, HashSet
, Hashtable
.
Il Javadoc per HashMap
dice:
Implementazione basata sulla tabella Hash dell'interfaccia della mappa. Questo l'implementazione fornisce tutte le operazioni di mappa opzionali e consente valori null e la chiave null.
Il Javadoc per HashSet
dice:
Questa classe implementa l'interfaccia Set, sostenuta da una tabella hash (in realtà un'istanza HashMap). Non fornisce alcuna garanzia in merito alla ordine di iterazione del set; in particolare, non garantisce che l'ordine rimarrà costante nel tempo.
Il Javadoc per Hashtable
dice:
Questa classe implementa una tabella hash, che associa le chiavi ai valori. Qualsiasi l'oggetto non nullo può essere utilizzato come chiave o come valore.
È confuso che tutti implementino il hash table
. Implementano il concetto di tabella hash ?
Sembra che tutti questi siano collegati tra loro, ma non sono in grado di comprenderlo appieno.
Qualcuno può aiutarmi a capire questo concetto in un linguaggio semplice.
4 answers
Le interfacce Set
e Map
di Java specificano due tipi di raccolta molto diversi. A Map
è, concettualmente, proprio quello che sembra: una mappatura da un set di oggetti (le chiavi) a un altro set (i valori). A Set
è anche proprio quello che sembra: una raccolta di oggetti (senza altra struttura). Hashtable
e HashMap
implementano entrambi Map
, HashSet
implementa Set
e tutti usano codici hash per chiavi/oggetti contenuti nelle raccolte per migliorare le prestazioni.
Hashtable
e HashMap
Hashtable
è una classe legacy che quasi sempre dovrebbe essere evitata a favore di HashMap
. Fanno essenzialmente la stessa cosa, tranne che la maggior parte dei metodi in Hashtable
sono sincronizzati, rendendo le singole chiamate di metodo thread-safe.1 È necessario fornire la propria sincronizzazione o un altro meccanismo di sicurezza del thread se si utilizzano più thread e HashMap
.
Il problema con Hashtable
è che la sincronizzazione di ogni chiamata di metodo (che è un'operazione non insignificante) è di solito la cosa sbagliata. O non è necessaria la sincronizzazione o, dal punto di vista della logica dell'applicazione, è necessario sincronizzare le transazioni che si estendono su più chiamate di metodo. Poiché era impossibile rimuovere semplicemente la sincronizzazione a livello di metodo da Hashtable
senza interrompere il codice esistente, gli autori del framework Collections dovevano creare una nuova classe; quindi HashMap
. È anche un nome migliore, poiché diventa chiaro che è una specie di Map
.
Oh, se lo fai hai bisogno di sincronizzazione a livello di metodo, non dovresti ancora usare Hashtable
. Invece, puoi chiamare Collections.synchronizedMap()
per trasformare qualsiasi mappa in una sincronizzata. In alternativa, è possibile utilizzare ConcurrentHashMap
, che, secondo i documenti: "obbedisce alla stessa specifica funzionale di Hashtable
" ma ha prestazioni migliori e funzionalità aggiuntive (come putIfAbsent()
).
1Ci sono altre differenze (meno significative, a mio avviso) come HashMap
che supportano i valori null
e chiave.
HashSet
In termini di funzionalità, HashSet
non ha nulla a che fare con HashMap
. Succede di usare un HashMap
internamente per implementare la funzionalità Set
. Per qualche ragione, gli sviluppatori del framework Collections hanno pensato che sarebbe stata una buona idea rendere questo dettaglio di implementazione interno parte della specifica pubblica per la classe. (Questo è stato un errore, a mio avviso.)
Hashtable era una vecchia classe creata prima che Java avesse generici. È solo in giro ancora per la compatibilità all'indietro. Usa invece HashMap.
Usa HashSet quando non hai bisogno di mappare le chiavi ai valori. È costruito sullo stesso algoritmo delle tabelle hash, ma viene utilizzato per uno scopo fondamentalmente diverso.
HashMap e HashTable ereditano entrambi l'interfaccia della mappa.e hanno quasi lo stesso lavoro e proprietà.Ma le principali differenze sono le seguenti: -
1.Hashmap è una mappa non ordinata di coppie di chiavi e valori.E possiamo avere la chiave null o coppie di valori all'interno di una hashmap.Anche una hashmap non è sincronizzata (cioè non thread safe più thread possono accedervi e modificarlo contemporaneamente.) Ma possiamo creare esternamente una hashmap thread-safe.So se non stiamo considerando i problemi di sincronizzazione allora hashmap è preferibile.
2.HashTable: - Un hashMap sincronizzato (cioè un hashmap thread safe).Ma le chiavi e le coppie di valori in questo caso non lo sono mai null.In a Hashtable specifichiamo un oggetto che viene utilizzato come chiave e il valore che vogliamo associare a quella chiave. La chiave viene quindi hash e il codice hash risultante viene utilizzato come indice in cui il valore viene memorizzato all'interno della tabella
3.HashSet: - Un hashset eredita l'interfaccia set e alla fine si basa anche su hashtable(o possiamo dire profondamente connesso solo alla nostra hashmap) ma in questo caso le coppie di chiavi e valori sono sempre univoche senza valori duplicati consentiti.ma i valori della chiave null sono consentiti.Gli oggetti vengono inseriti in base al loro codice hash.
In una conclusione possiamo dire che tutte e tre le collezioni si sono collegate all'interfaccia della mappa su e tutto.
Hashtable è sincronizzato ma HashMap non lo è, ma puoi sincronizzare HashMap con l'aiuto delle raccolte di metodi.synchronizedMap (). Hashtable, HashMap e HashSet sono woking in base alla struttura dei dati della tabella Hash. È possibile utilizzare una chiave null e quale tipo di valori null si desidera per HashMap ma Hashtable non consente valori null key o null. Fondamentalmente sotto HashSet funziona HashMap dove il valore è Oggetto, quindi i valori HashSet sono unici perché le chiavi HashMap sono uniche. Quindi per mettere chiave coppia di valori in Hashmap o Hashtable o mettendo l'elemento in HashSet è necessario ovveride hashcode ed è uguale a metodi dalla classe Object per correggere il funzionamento di queste implementazioni. Questo perché sotto queste implementazioni funzionano l'algoritmo della tabella Hash e l'hashcode, equals è necessario per inserire i valori nel bucket giusto. È importante sapere che è necessario utilizzare come chiavi String o qualsiasi altra classe wrapper come Integer, questo perché questi oggetti sono immutabili e possono essere buone chiavi per questo implementazioni o puoi creare la tua classe immutabile e usarla come chiave. Utilizzare oggetti immutabili come chiave è una buona pratica perché dopo la creazione non possono cambiare il loro stato, quindi l'hashcode è sempre lo stesso.