L'aggiunta di un valore duplicato a un HashSet / HashMap sostituisce il valore precedente


137

Si prega di considerare la parte di codice seguente:

HashSet hs = new HashSet();
hs.add("hi"); -- (1)
hs.add("hi"); -- (2)

hs.size()darà 1 in quanto HashSetnon consente duplicati, quindi verrà memorizzato solo un elemento.

Voglio sapere se aggiungiamo l'elemento duplicato, quindi sostituisce l'elemento precedente o semplicemente non lo aggiunge?

Inoltre, cosa accadrà usando HashMapper lo stesso caso?

Risposte:


247

Nel caso di HashMap, sostituisce il vecchio valore con quello nuovo.

Nel caso di HashSet, l'elemento non è inserito.


1
Non sei sicuro di cosa mi sto perdendo, ma il codice sorgente sembra indicare diversamente? Vedo che non fanno un controllo sul supporto HashMapper vedere se keyesiste già prima di chiamare putil supporto map?
mystarrocks,

10
@mystarrocks: la chiave è l'elemento di Set, e non viene mai sostituito put()dall'operazione.
Keppil,

1
ah ho capito adesso. Ho capito che la chiave è l'elemento di Set, ma ho appena capito che put()sovrascriverà solo il valore, non la chiave. In questo caso, è lo stesso valore messo di nuovo accanto alla chiave, il che potrebbe essere o meno meglio che verificare se la chiave esiste e mettere. Ad ogni modo, capisco come funziona.
mystarrocks,

Solo curioso, perché HashMap e HashSet scelgono di essere così?
Helin Wang,

@HelinWang: non penso che fosse pianificato, penso che sia solo un effetto HashSetdell'implementazione sotto forma di a HashMap. Difficile da sapere, a meno che tu non sia uno degli sviluppatori delle classi.
Keppil,

47

La prima cosa che devi sapere è che si HashSetcomporta come un Set, il che significa che aggiungi l'oggetto direttamente a HashSete non può contenere duplicati. Devi solo aggiungere il tuo valore direttamente in HashSet.

Tuttavia, HashMapè un Maptipo. Ciò significa che ogni volta che aggiungi una voce, aggiungi una coppia chiave-valore.

In HashMappuoi avere valori duplicati, ma non chiavi duplicate. Nella HashMapnuova voce sostituirà quella vecchia. La voce più recente sarà nel HashMap.

Comprensione del collegamento tra HashMap e HashSet:

Ricorda, HashMapnon puoi avere chiavi duplicate. Dietro la scena HashSetusa a HashMap.

Quando si tenta di aggiungere qualsiasi oggetto in a HashSet, questa voce viene effettivamente memorizzata come chiave nel HashMap- lo stesso HashMapche viene utilizzato dietro la scena di HashSet. Poiché questo sottostante ha HashMapbisogno di una coppia chiave-valore, per noi viene generato un valore fittizio.

Ora, quando provi a inserire un altro oggetto duplicato nello stesso HashSet, tenterà di nuovo di inserirlo come chiave nella parte HashMapsottostante. Tuttavia, HashMapnon supporta i duplicati. Quindi, si HashSetotterrà comunque un solo valore di quel tipo. Come nota a margine, per ogni chiave duplicata, poiché il valore generato per la nostra voce in HashSet è un valore casuale / fittizio, la chiave non viene affatto sostituita. verrà ignorato in quanto la rimozione della chiave e l'aggiunta della stessa chiave (il valore fittizio è lo stesso) non avrebbe alcun senso.

Sommario:

HashMapconsente duplicati values, ma non keys. HashSetnon può contenere duplicati.

Per stabilire se l'aggiunta di un oggetto è stata completata correttamente o meno, è possibile verificare il booleanvalore restituito quando si chiama .add() e vedere se restituisce trueo false. Se è tornato true, è stato inserito.


HashMap allows duplicate valuesHashMap sostituisce il vecchio valore con quello nuovo.
Alex78191,

20

I documenti sono abbastanza chiari su questo: HashSet.add non sostituisce:

Aggiunge l'elemento specificato a questo set se non è già presente. Più formalmente, aggiunge l'elemento specificato e a questo set se questo set non contiene alcun elemento e2 tale che (e == null? E2 == null: e.equals (e2)). Se questo set contiene già l'elemento, la chiamata lascia il set invariato e restituisce false.

Ma si sostituirà:HashMap.put

Se la mappa in precedenza conteneva un mapping per la chiave, il vecchio valore viene sostituito.


4

Nel caso di HashSet, NON lo sostituisce.

Dai documenti:

http://docs.oracle.com/javase/6/docs/api/java/util/HashSet.html#add(E )

"Aggiunge l'elemento specificato a questo set se non è già presente. Più formalmente, aggiunge l'elemento specificato e a questo set se questo set non contiene alcun elemento e2 tale che (e == null? E2 == null: e.equals ( e2)). Se questo set contiene già l'elemento, la chiamata lascia invariato il set e restituisce false. "


1

Correggimi se sbaglio, ma quello che stai ottenendo è che con le stringhe, "Ciao" == "Ciao" non sempre si rivela vero (perché non sono necessariamente lo stesso oggetto).

Il motivo per cui stai ricevendo una risposta pari a 1 è perché JVM riutilizzerà gli oggetti stringhe ove possibile. In questo caso, JVM sta riutilizzando l'oggetto stringa e quindi sovrascrivendo l'elemento in Hashmap / Hashset.

Ma questo comportamento non è garantito (perché potrebbe essere un oggetto stringa diverso con lo stesso valore "Ciao"). Il comportamento che vedi è solo a causa dell'ottimizzazione della JVM.


0

È necessario verificare prima il metodo put nella mappa Hash poiché HashSet è sottoposto a backup da HashMap

  1. Quando aggiungi un valore duplicato, pronuncia una stringa "One" in HashSet,
  2. Una voce ("one", PRESENT) verrà inserita in Hashmap (per tutti i valori aggiunti in set, il valore sarà "PRESENT" che se di tipo Object)
  3. Hashmap aggiunge la voce in Mappa e restituisce il valore, che in questo caso è "PRESENTE" o null se la voce non è presente.
  4. Il metodo di aggiunta di Hashset restituisce quindi true se il valore restituito da Hashmap è uguale a null, altrimenti false indica che esiste già una voce ...

0

Per dirlo in modo diverso: quando si inserisce una coppia chiave-valore in una HashMap in cui la chiave esiste già (in un certo senso hashvalue () fornisce lo stesso valore e uguale () è vero, ma i due oggetti possono comunque differire in diversi modi ), la chiave non viene sostituita ma il valore viene sovrascritto. La chiave viene utilizzata solo per ottenere l'hashvalue () e trovare il valore nella tabella con esso. Poiché HashSet utilizza le chiavi di una HashMap e imposta valori arbitrari che non contano (per l'utente), di conseguenza neanche gli Elementi del Set vengono sostituiti.


0

HashMapfondamentalmente contiene ciò Entryche successivamente contiene Key(Object)e Value(Object).Internamente HashSetsono HashMape HashMapsostituiscono i valori come alcuni di voi hanno già indicato..ma sostituisce davvero le chiavi ??? No ..e questo è il trucco qui. HashMapmantiene il suo valore come chiave nel sottostante HashMape il valore è solo un oggetto fittizio. Quindi, se si tenta di reinserire lo stesso valore in HashMap (Chiave nella mappa sottostante). Sostituisce semplicemente il valore fittizio e non la chiave (Valore per HashSet).

Guarda il codice seguente per la classe HashSet:

public boolean  [More ...] add(E e) {

   return map.put(e, PRESENT)==null;
}

Qui e è il valore di HashSet ma la chiave per map.and sottostante non viene mai sostituita. Spero di essere in grado di cancellare la confusione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.