Proszę wziąć pod uwagę poniższy fragment kodu:
HashSet hs = new HashSet();
hs.add("hi"); -- (1)
hs.add("hi"); -- (2)
hs.size()
da 1, ponieważ HashSet
nie zezwala na duplikaty, więc tylko jeden element zostanie zapisany.
Chcę wiedzieć, czy dodajemy zduplikowany element, czy zastępuje on poprzedni element, czy po prostu go nie dodaje?
Co się stanie HashMap
z tym samym przypadkiem?
java
hashmap
duplicates
hashset
Anand
źródło
źródło
HashMap
aby sprawdzić, czykey
już istnieje przed wywołaniemput
podkładumap
?Set
i nigdy nie jest zastępowany przezput()
operację.Set
, ale właśnie zdałem sobie sprawę, żeput()
nadpisuje tylko wartość, a nie klucz. W tym przypadku jest to ta sama wartość umieszczona ponownie obok klucza, co może, ale nie musi, być lepsze niż sprawdzenie, czy klucz istnieje i wstawienie. Tak czy inaczej, rozumiem, jak to działa.HashSet
wdrożenia w formie plikuHashMap
. Trudno to jednak wiedzieć, chyba że jesteś jednym z twórców klas.Pierwszą rzeczą, którą musisz wiedzieć, jest to, że
HashSet
działa jak aSet
, co oznacza, że dodajesz swój obiekt bezpośrednio doHashSet
i nie może zawierać duplikatów. Po prostu dodajesz swoją wartość bezpośrednioHashSet
.Jednak
HashMap
jest toMap
typ. Oznacza to, że za każdym razem, gdy dodajesz wpis, dodajesz parę klucz-wartość.W
HashMap
możesz mieć zduplikowane wartości, ale nie zduplikowane klucze. WHashMap
nowym wpisie zastąpi stary. Najnowszy wpis będzie wHashMap
.Zrozumienie powiązania między HashMap i HashSet:
Pamiętaj,
HashMap
nie możesz mieć zduplikowanych kluczy. Za scenąHashSet
używaHashMap
.Kiedy próbujesz dodać dowolny obiekt do
HashSet
, ten wpis jest w rzeczywistości przechowywany jako klucz wHashMap
- tym samym,HashMap
który jest używany za scenąHashSet
. Ponieważ tenHashMap
element bazowy wymaga pary klucz-wartość, generowana jest dla nas wartość fikcyjna.Teraz, gdy spróbujesz wstawić inny zduplikowany obiekt do tego samego
HashSet
, ponownie spróbuje wstawić go jako klucz doHashMap
leżącego poniżej. JednakHashMap
nie obsługuje duplikatów. DlategoHashSet
nadal będzie skutkować posiadaniem tylko jednej wartości tego typu. Na marginesie, dla każdego zduplikowanego klucza, ponieważ wartość wygenerowana dla naszego wpisu w HashSet jest jakąś losową / fikcyjną wartością, klucz nie jest w ogóle zastępowany. zostanie zignorowane, ponieważ usunięcie klucza i dodanie z powrotem tego samego klucza (fikcyjna wartość jest taka sama) nie miałoby żadnego sensu.Podsumowanie:
HashMap
umożliwia duplikowanievalues
, ale niekeys
.HashSet
nie może zawierać duplikatów.Aby pobawić się, czy dodanie obiektu zakończyło się pomyślnie, czy nie, możesz sprawdzić
boolean
wartość zwracaną podczas wywołania.add()
i zobaczyć, czy zwracatrue
lubfalse
. Jeśli zwróciłtrue
, został włożony.źródło
HashMap allows duplicate values
HashMap zastępuje starą wartość nową.W docs są całkiem jasno:
HashSet.add
nie wymienić:Ale będzie wymienić:
HashMap.put
źródło
W przypadku HashSet NIE zastępuje go.
Z dokumentów:
http://docs.oracle.com/javase/6/docs/api/java/util/HashSet.html#add(E )
"Dodaje określony element do tego zestawu, jeśli jeszcze go nie ma. Bardziej formalnie dodaje określony element e do tego zestawu, jeśli ten zestaw nie zawiera elementu e2 takiego, że (e == null? E2 == null: e.equals ( e2)). Jeśli ten zestaw już zawiera element, wywołanie pozostawia zestaw bez zmian i zwraca fałsz. "
źródło
Popraw mnie, jeśli się mylę, ale to, do czego zmierzasz, to to, że w przypadku łańcuchów „Hi” == „Hi” nie zawsze wychodzi jako prawdą (ponieważ niekoniecznie są one tym samym obiektem).
Powodem, dla którego otrzymujesz odpowiedź 1, jest jednak to, że maszyna JVM ponownie użyje obiektów łańcuchowych, jeśli to możliwe. W tym przypadku maszyna JVM ponownie wykorzystuje obiekt łańcuchowy, nadpisując w ten sposób element w Hashmap / Hashset.
Ale nie masz gwarancji takiego zachowania (ponieważ może to być inny obiekt ciągu o tej samej wartości „Hi”). Zachowanie, które widzisz, jest spowodowane optymalizacją maszyny JVM.
źródło
Musisz najpierw sprawdzić metodę put w mapie Hash, ponieważ HashSet jest kopiowany przez HashMap
źródło
Mówiąc inaczej: kiedy wstawisz parę klucz-wartość do HashMap, gdzie klucz już istnieje (w pewnym sensie hashvalue () daje tę samą wartość und equal () jest prawdziwe, ale te dwa obiekty mogą nadal różnić się na kilka sposobów ), klucz nie zostanie zastąpiony, ale wartość zostanie nadpisana. Klucz jest po prostu używany do pobrania hashvalue () i znalezienia z nią wartości w tabeli. Ponieważ HashSet używa kluczy HashMap i ustawia dowolne wartości, które tak naprawdę nie mają znaczenia (dla użytkownika), w rezultacie elementy zestawu również nie są zastępowane.
źródło
HashMap
w zasadzie zawiera,Entry
które następnie zawieraKey(Object)
i.Value(Object)
WewnętrznieHashSet
sąHashMap
iHashMap
zastępują wartości, jak niektórzy z was już wskazali, ale czy to naprawdę zastępuje klucze ??? Nie .. i na tym polega sztuczka.HashMap
zachowuje swoją wartość jako klucz w źródle,HashMap
a wartość jest tylko fikcyjnym obiektem, więc jeśli spróbujesz ponownie wstawić tę samą wartość w HashMap (klucz w podstawowej mapie) .Zastępuje po prostu wartość fikcyjną, a nie klucz (wartość dla HashSet).Spójrz na poniższy kod dla klasy HashSet:
Tutaj e jest wartością dla HashSet, ale klucz dla podstawowej mapy. A klucz nigdy nie jest zastępowany. Mam nadzieję, że uda mi się usunąć zamieszanie.
źródło