Jeśli mijam te same kluczowe wielokrotnie do HashMap
„s put
metody, co dzieje się z pierwotnej wartości? A jeśli nawet wartość się powtarza? Nie znalazłem żadnej dokumentacji na ten temat.
Przypadek 1: Nadpisane wartości klucza
Map mymap = new HashMap();
mymap.put("1","one");
mymap.put("1","not one");
mymap.put("1","surely not one");
System.out.println(mymap.get("1"));
Dostajemy surely not one
.
Przypadek 2: Zduplikowana wartość
Map mymap = new HashMap();
mymap.put("1","one");
mymap.put("1","not one");
mymap.put("1","surely not one");
// The following line was added:
mymap.put("1","one");
System.out.println(mymap.get("1"));
Dostajemy one
.
Ale co dzieje się z innymi wartościami? Uczyłem studenta podstaw i zostałem o to poproszony. Czy jest Map
jak wiadro, do którego odwołuje się ostatnia wartość (ale w pamięci)?
Odpowiedzi:
Z definicji
put
polecenie zastępuje poprzednią wartość powiązaną z danym kluczem na mapie (koncepcyjnie jak operacja indeksowania tablic dla typów pierwotnych).Mapa po prostu upuszcza swoje odniesienie do wartości. Jeśli nic innego nie zawiera odwołania do obiektu, obiekt ten kwalifikuje się do odśmiecania. Ponadto Java zwraca dowolną poprzednią wartość związaną z danym kluczem (lub
null
jeśli nie występuje), dzięki czemu możesz określić, co tam było i zachować referencję, jeśli to konieczne.Więcej informacji tutaj: HashMap Doc
źródło
Odpowiedź możesz znaleźć w javadoc mapy # put (K, V) (która faktycznie coś zwraca):
Jeśli więc nie przypiszesz zwracanej wartości podczas wywoływania
mymap.put("1", "a string")
, staje się ona po prostu bez odniesienia, a zatem kwalifikuje się do odśmiecania.źródło
null
) jak udokumentowano tylko powyżej w javadoc tak, tak, to jest to, co mam na myśli. Czy to naprawdę może być źle interpretowane?Poprzednia wartość klucza jest usuwana i zastępowana nową.
Jeśli chcesz zachować wszystkie wartości podane w kluczu, możesz rozważyć wdrożenie czegoś takiego:
źródło
jest to funkcja Klucz / Wartość i nie można mieć duplikatu klucza dla kilku wartości, ponieważ gdy chcesz uzyskać rzeczywistą wartość, która z wartości należy do wpisanego klucza
w twoim przykładzie, gdy chcesz uzyskać wartość „1”, która to jest to ?!
to powody, dla których warto mieć unikalny klucz dla każdej wartości, ale możesz spróbować sztuczki według standardowej biblioteki Java:
i możesz użyć tego w ten sposób:
a wynikiem wydruków są:
źródło
Kojarzy określoną wartość z określonym kluczem na tej mapie. Jeśli mapa poprzednio zawierała mapowanie klucza, stara wartość zostanie zastąpiona.
źródło
To zastępuje istniejącą wartość na mapie dla odpowiedniego klucza. A jeśli nie istnieje żaden klucz o tej samej nazwie, tworzy klucz o podanej wartości. na przykład:
Klucz wyjściowy = „1”, wartość = „dwa”
Tak więc poprzednia wartość zostaje zastąpiona.
źródło
Na twoje pytanie, czy mapa była jak wiadro: nie.
To jest jak lista z
name=value
parami, podczasname
gdy nie musi to być ciąg znaków (może jednak).Aby uzyskać element, przekazujesz klucz do metody get (), która w zamian daje ci przypisany obiekt.
A mapa hash oznacza, że jeśli próbujesz odzyskać swój obiekt za pomocą metody get-, nie porówna on rzeczywistego obiektu z tym, który podałeś, ponieważ musiałby iterować swoją listę i porównywać () klucz podałeś bieżący element.
To byłoby nieefektywne. Zamiast tego, bez względu na to, z czego składa się twój obiekt, oblicza tak zwany kod skrótu z obu obiektów i porównuje je. Łatwiej jest porównać dwa
int
s zamiast dwóch całych (być może bardzo złożonych) obiektów. Możesz sobie wyobrazić hashcode jako podsumowanie o określonej długości (int), dlatego nie jest unikalny i ma kolizje. Zasady dotyczące kodu skrótu znajdują się w dokumentacji, do której wstawiłem łącze.Jeśli chcesz dowiedzieć się więcej na ten temat, możesz zajrzeć do artykułów na javapractices.com i technofundo.com
pozdrowienia
źródło
Zawsze używałem:
gdybym chciał zastosować wiele rzeczy do jednego klucza identyfikującego.
zawsze możesz zrobić coś takiego i stworzyć sobie labirynt!
źródło
Mapy z JDK nie są przeznaczone do przechowywania danych pod zduplikowanymi kluczami.
W najlepszym razie nowa wartość zastąpi poprzednie.
Gorszym scenariuszem jest wyjątek (np. Gdy próbujesz zebrać go jako strumień):
Brak duplikatów:
Stream.of("one").collect(Collectors.toMap(x -> x, x -> x))
Powielony strumień:
Stream.of("one", "not one", "surely not one").collect(Collectors.toMap(x -> 1, x -> x))
Aby poradzić sobie ze zduplikowanymi kluczami - użyj innego pakietu, np .: https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/Multimap.html
Istnieje wiele innych implementacji dotyczących zduplikowanych kluczy. Są one potrzebne w Internecie (np. Zduplikowane klucze cookie, nagłówki HTTP mogą mieć te same pola, ...)
Powodzenia! :)
źródło
Collectors.toMap()
ma trzeci argument - funkcję scalania. Jeśli chcemy po prostu zastąpić ostatni duplikat elementu:Stream.of("one", "two", "one").collect(Collectors.toMap(x -> x, x -> x, (key1, key2) -> key2))
. link"one", "not one", "surely not one"
nie spowodują żadnych powtarzających się błędów klucza z powodu różnych ciągów znaków.BTW, jeśli chcesz trochę semantyki, takiej jak wstaw tylko, jeśli ten klucz nie istnieje. możesz używać
concurrentHashMap
zputIfAbsent()
funkcją. Sprawdź to:https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html#put(K,%20V)
concurrentHashMap
jest bezpieczny dla wątków i ma wysoką wydajność, ponieważ wykorzystuje mechanizm „ blokowania pasków ” w celu zwiększenia przepustowości.źródło
Tak, oznacza to, że wszystkie 1 klucze z wartością są zastąpione ostatnią wartością dodaną, a tutaj dodajesz „na pewno nie jeden”, więc wyświetli się tylko „na pewno nie jeden”.
Nawet jeśli próbujesz wyświetlić za pomocą pętli, wyświetli również tylko jeden klucz i wartość, które mają ten sam klucz.
źródło
Oznacza mapę skrótów nie zezwala na duplikaty, jeśli poprawnie zastąpiłeś metody equals i hashCode ().
HashSet używa również HashMap wewnętrznie, patrz dokument źródłowy
źródło