Czy jest możliwe HashMap
zwrócenie wartości domyślnej dla wszystkich kluczy, których nie ma w zestawie?
java
dictionary
hashmap
Larry
źródło
źródło
getOrDefault()
łączaOdpowiedzi:
[Aktualizacja]
Jak zauważyli inni odpowiedzi i komentatorzy, od wersji Java 8 możesz po prostu zadzwonić
Map#getOrDefault(...)
.[Oryginalny]
Nie ma implementacji Map, która robi to dokładnie, ale zaimplementowanie własnej przez rozszerzenie HashMap byłoby trywialne:
źródło
(v == null)
do(v == null && !this.containsKey(k))
w przypadku, gdy celowo dodalinull
wartość. Wiem, to tylko przypadek narożny, ale autor może się na to natknąć.!this.containsValue(null)
. To jest nieco inne niż!this.containsKey(k)
.containsValue
Rozwiązanie zawiedzie, jeśli jakiś inny klucz został jednoznacznie przypisana wartośćnull
. Na przykład: wmap = new HashMap(); map.put(k1, null); V v = map.get(k2);
tym przypadkuv
nadal będzienull
, prawda?W Javie 8 użyj Map.getOrDefault . Pobiera klucz i wartość do zwrócenia, jeśli nie zostanie znaleziony pasujący klucz.
źródło
getOrDefault
jest bardzo ładny, ale wymaga domyślnej definicji przy każdym dostępie do mapy. Jednokrotne zdefiniowanie wartości domyślnej przyniosłoby również korzyści związane z czytelnością podczas tworzenia statycznej mapy wartości.private static String get(Map map, String s) { return map.getOrDefault(s, "Error"); }
Użyj DefaultedMap Commons, jeśli nie masz ochoty wymyślać koła na nowo, np.
Możesz również przekazać istniejącą mapę, jeśli nie jesteś odpowiedzialny za jej tworzenie.
źródło
Java 8 wprowadziła ładną domyślną metodę computeIfAbsent do
Map
interfejsu, która przechowuje leniwą wartość obliczoną i dlatego nie przerywa kontraktu mapy:Pochodzenie: http://blog.javabien.net/2014/02/20/loadingcache-in-java-8-without-guava/
Disclamer: Ta odpowiedź nie pasuje dokładnie do tego, co zadał OP, ale może być przydatna w niektórych przypadkach dopasowanie tytułu pytania, gdy liczba kluczy jest ograniczona, a buforowanie różnych wartości byłoby opłacalne. Nie należy go używać w przeciwnym przypadku z dużą ilością kluczy i tą samą wartością domyślną, ponieważ niepotrzebnie marnuje to pamięć.
źródło
Nie możesz po prostu utworzyć statycznej metody, która robi dokładnie to?
źródło
Możesz po prostu utworzyć nową klasę, która dziedziczy HashMap i dodać metodę getDefault. Oto przykładowy kod:
Myślę, że nie powinieneś nadpisywać metody get (klawisz K) w swojej implementacji, z powodów określonych przez Eda Stauba w swoim komentarzu oraz z powodu zerwania kontraktu interfejsu Map (może to potencjalnie prowadzić do trudnych do znalezienia robaki).
źródło
get
metody. Z drugiej strony - Twoje rozwiązanie nie pozwala na używanie klasy przez interfejs, co często może mieć miejsce.Posługiwać się:
źródło
Robi to domyślnie. Wraca
null
.źródło
HashMap
tylko dla tej funkcji, kiedynull
jest w porządku.NullObject
wzorca lub nie chcesz rozpraszać kontroli null w całym kodzie - pragnienie, które całkowicie rozumiem.W Javie 8+
źródło
znalazłem LazyMap jest całkiem pomocny.
To pozwala zrobić coś takiego:
Wywołanie do
get
tworzy wartość domyślną dla danego klucza. Możesz określić, jak utworzyć wartość domyślną z argumentem fabryki naLazyMap.lazyMap(map, factory)
. W powyższym przykładzie mapa jest inicjalizowana jako nowaAtomicInteger
z wartością 0.źródło
List<String>
- używając zaakceptowanej odpowiedzi zaryzykowałbym użycie tej samej listy dla każdego nowego klucza, zamiast (powiedzmy) anew ArrayList<String>()
z fabryki.Nie bezpośrednio, ale możesz rozszerzyć klasę, aby zmodyfikować jej metodę get. Oto gotowy do użycia przykład: http://www.java2s.com/Code/Java/Collections-Data-Structure/ExtendedVersionofjavautilHashMapthatprovidesanextendedgetmethodaccpetingadefaultvalue.htm
źródło
Przykładowe zastosowanie:
źródło
Musiałem odczytać wyniki zwrócone z serwera w formacie JSON, gdzie nie mogłem zagwarantować, że pola będą obecne. Używam klasy org.json.simple.JSONObject, która jest pochodną HashMap. Oto kilka funkcji pomocniczych, których użyłem:
źródło
W mieszanych projektach Java / Kotlin rozważ także Map.withDefault Kotlina .
źródło