Czy sprawdzanie istnienia klucza w HashMap jest zawsze konieczne?
Mam HashMap z powiedzmy 1000 wpisów i szukam poprawy wydajności. Jeśli dostęp do HashMap jest uzyskiwany bardzo często, sprawdzanie istnienia klucza przy każdym dostępie spowoduje duże obciążenie. Zamiast tego, jeśli klucz nie jest obecny i stąd występuje wyjątek, mogę go złapać. (kiedy wiem, że to się zdarza rzadko). Spowoduje to zmniejszenie dostępu do HashMap o połowę.
To może nie być dobra praktyka programowania, ale pomoże mi zmniejszyć liczbę dostępów. A może coś tu brakuje?
[ Aktualizacja ] Nie mam wartości zerowych w HashMap.
Odpowiedzi:
Czy kiedykolwiek przechowujesz wartość zerową? Jeśli nie, możesz po prostu:
W przeciwnym razie mogłyby po prostu sprawdzić na istnienie, jeśli uzyska wartość NULL zwracane:
źródło
get
jest w porządku i unikasz wykonywania dwóch przeglądów, gdy potrzebujesz także wartości.if(value!=null || map.containsKey(key))
dla drugiej części. Przynajmniej jeśli chcesz zrobić to samo w obu przypadkach - bez powtarzającego się kodu. Będzie działać z powodu zwarcia .Nic nie zyskasz, sprawdzając, czy klucz istnieje. To jest kod
HashMap
:Wystarczy sprawdzić, czy zwracana wartość dla
get()
jest inna niżnull
.To jest kod źródłowy HashMap.
Zasoby :
Kod źródłowy HashMapZłyźródło
Lepszym sposobem jest użycie
containsKey
metodyHashMap
. Jutro ktoś doda null do mapy. Należy odróżnić obecność klucza od klucza o wartości zerowej.źródło
null
całkowitemu przechowywaniu .Czy masz na myśli, że masz kod podobny do tego?
wszędzie wokoło ? Następnie powinieneś po prostu sprawdzić, czy
map.get(key)
zwrócił wartość null i to wszystko. Nawiasem mówiąc, HashMap nie zgłasza wyjątków dla brakujących kluczy, zamiast tego zwraca null. Jedynym przypadkiem, w którymcontainsKey
jest to potrzebne, jest przechowywanie wartości zerowych w celu odróżnienia wartości zerowej od wartości brakującej, ale zwykle uważa się to za złą praktykę.źródło
Po prostu użyj
containsKey()
dla jasności. Jest szybki i utrzymuje kod w czystości i czytelności. Chodzi oHashMap
to, że wyszukiwanie klucza jest szybkie, po prostu upewnij się, żehashCode()
iequals()
są poprawnie zaimplementowane.źródło
źródło
Możesz także użyć tej
computeIfAbsent()
metody wHashMap
klasie.W poniższym przykładzie
map
przechowuje listę transakcji (liczb całkowitych), które są stosowane do klucza (nazwa konta bankowego). Aby dodać 2 transakcje100
i200
dochecking_account
można napisać:W ten sposób nie musisz sprawdzać, czy klucz
checking_account
istnieje, czy nie.computeIfAbsent()
.Naprawdę elegancki! 👍
źródło
Zwykle używam tego idiomu
Oznacza to, że uderzyłeś w mapę tylko dwa razy, jeśli brakuje klucza
źródło
źródło
Odpowiedź Jona Skeeta dobrze odnosi się do dwóch scenariuszy (mapa z
null
wartością, a nienull
wartością) w efektywny sposób.Jeśli chodzi o wpisy liczbowe i problem z wydajnością, chciałbym coś dodać.
Mapa z 1000 wpisów nie jest wielką mapą.
Jak również mapa z 5.000 lub 10.000 wpisów.
Map
są zaprojektowane do szybkiego wyszukiwania przy takich wymiarach.Teraz zakłada się, że
hashCode()
z klawiszy mapy zapewnia dobrą dystrybucję.Jeśli możesz użyć
Integer
jako typu klucza, zrób to.Ta
hashCode()
metoda jest bardzo wydajna, ponieważ kolizje nie są możliwe dla unikalnychint
wartości:Jeśli dla klucza musisz użyć innego wbudowanego typu, jak
String
na przykład często używanyMap
, możesz mieć pewne kolizje, ale od 1 tysiąca do kilku tysięcy obiektów wMap
, powinieneś mieć ich bardzo mało jakoString.hashCode()
metodę zapewnia dobrą dystrybucję.Jeśli używasz niestandardowego typu, zastąp
hashCode()
iequals()
poprawnie, i upewnij się, że ogólniehashCode()
zapewnia to sprawiedliwą dystrybucję.Możesz odnieść się do punktu 9,
Java Effective
dotyczy go.Oto post, który szczegółowo opisuje sposób.
źródło