„Być może problemem nie jest to, że nic nam nie przeszkadza, ale to, że przeszkadzamy”.
bmargulies
3
W kolekcjach Guava, Google, wiele klas nie dopuszcza wartości null, a powodem tego jest to, że 95% przypadków nie wymaga wartości null i mogą reprezentować błędy, potencjalnie trudne do znalezienia.
stivlo
Dziwne jest to, że ConcurrentHashMapnie obsługuje klawiszy zerowych, podczas gdy HashMaptak.
codepleb
2
Tylko HashMap dopuszcza null :)
subhashis
Odpowiedzi:
126
Nie jestem pewien, o co pytasz, ale jeśli szukasz przykładu, kiedy chciałoby się użyć klucza zerowego, często używam ich na mapach, aby przedstawić domyślny przypadek (tj. Wartość, która powinna być użyta jeśli nie ma podanego klucza):
Map<A, B> foo;
A search;
B val = foo.containsKey(search) ? foo.get(search) : foo.get(null);
HashMapobsługuje klucze o wartości null specjalnie (ponieważ nie może wywołać .hashCode()obiektu zerowego), ale wartości null nie są niczym specjalnym, są przechowywane na mapie jak wszystko inne
Więc jeśli .hashCode () nie jest możliwe na null, kto decyduje, do którego karetki wejdzie pusty klucz?
Pacerier,
26
@Pacerier Jest specjalna metoda w HashMap( putForNullKey), która to obsługuje; przechowuje to w tabeli 0
Michał Mrozek
1
@MichaelMrozek twoja ostatnia linia B val = foo.containsKey(search) ? foo.get(search) : foo.get(null);Myślę, że możemy po prostu wywołać metodę get na kluczu wyszukiwania, co da ten sam wynik. B val = foo.get(search);czy mógłbyś mnie poprawić, jeśli coś jest nie tak?
dheerajraaj
6
@ dheeraj92 Twój kod zostanie ustawiony valna, nulljeśli klucz nie istnieje; mój ustawia go na dowolne nullmapy na mapie. O to właśnie chodziło, zapisuję domyślną wartość niezerową pod nullkluczem w mapie i używam jej, jeśli rzeczywisty klucz nie istnieje
Michael Mrozek
28
Jednym z przykładów może być modelowanie drzew. Jeśli używasz HashMap do reprezentowania struktury drzewa, gdzie klucz jest elementem nadrzędnym, a wartością jest lista dzieci, wówczas wartościami nullklucza byłyby węzły główne.
Jednym z przykładów użycia nullwartości jest użycie HashMapjako pamięci podręcznej wyników kosztownej operacji (takiej jak wywołanie zewnętrznej usługi sieciowej), która może powrócić null.
Umieszczenie nullwartości na mapie pozwala następnie na rozróżnienie między przypadkiem, w którym operacja nie została wykonana dla danego klucza ( cache.containsKey(someKey)zwraca false), a gdzie operacja została wykonana, ale zwróciła nullwartość ( cache.containsKey(someKey)zwraca true, cache.get(someKey)zwraca null).
Bez nullwartości należałoby albo umieścić w pamięci podręcznej jakąś specjalną wartość, aby wskazać nullodpowiedź, albo po prostu w ogóle nie buforować tej odpowiedzi i wykonywać operację za każdym razem.
Dotychczasowe odpowiedzi uwzględniają tylko wartość posiadania nullklucza, ale pytanie dotyczy również any number of null values.
Korzyści płynące z przechowywania wartości nullw kluczu w HashMap są takie same jak w bazach danych itp. - można zapisać rozróżnienie między wartością, która jest pusta (np. Ciąg „”), a brakiem wartości w ogóle (null) .
Oto mój jedyny nieco wymyślony przykład przypadku, w którym nullklucz może być przydatny:
publicclassTimer{
privatestaticfinal Logger LOG = Logger.getLogger(Timer.class);
privatestaticfinal Map<String, Long> START_TIMES = new HashMap<String, Long>();
publicstaticsynchronizedvoidstart(){
long now = System.currentTimeMillis();
if (START_TIMES.containsKey(null)) {
LOG.warn("Anonymous timer was started twice without being stopped; previous timer has run for " + (now - START_TIMES.get(null).longValue()) +"ms");
}
START_TIMES.put(null, now);
}
publicstaticsynchronizedlongstop(){
if (! START_TIMES.containsKey(null)) {
return0;
}
return printTimer("Anonymous", START_TIMES.remove(null), System.currentTimeMillis());
}
publicstaticsynchronizedvoidstart(String name){
long now = System.currentTimeMillis();
if (START_TIMES.containsKey(name)) {
LOG.warn(name + " timer was started twice without being stopped; previous timer has run for " + (now - START_TIMES.get(name).longValue()) +"ms");
}
START_TIMES.put(name, now);
}
publicstaticsynchronizedlongstop(String name){
if (! START_TIMES.containsKey(name)) {
return0;
}
return printTimer(name, START_TIMES.remove(name), System.currentTimeMillis());
}
privatestaticlongprintTimer(String name, long start, long end){
LOG.info(name + " timer ran for " + (end - start) + "ms");
return end - start;
}
}
Jeśli próbujesz zatrzymać nieistniejący licznik czasu lub taki, który został już zatrzymany, powinien to być błąd, a nie zignorowany.
Załóż pozew Moniki
@QPaysTaxes - Zależy od Twojego zamiaru. Jeśli potrzebujesz lekkiego narzędzia, którego można łatwo używać, na ogół nie chcesz go mieć throw Exception. Poza tym to nie jest tak, że próba zatrzymania nieistniejącego lub już zatrzymanego timera jest czymś, z czego dzwoniący może ogólnie odzyskać.
aroth
1
Inny przykład: używam go do grupowania danych według daty. Ale niektóre dane nie mają daty. Mogę to zgrupować z nagłówkiem „NoDate”
ConcurrentHashMap
nie obsługuje klawiszy zerowych, podczas gdyHashMap
tak.Odpowiedzi:
Nie jestem pewien, o co pytasz, ale jeśli szukasz przykładu, kiedy chciałoby się użyć klucza zerowego, często używam ich na mapach, aby przedstawić domyślny przypadek (tj. Wartość, która powinna być użyta jeśli nie ma podanego klucza):
Map<A, B> foo; A search; B val = foo.containsKey(search) ? foo.get(search) : foo.get(null);
HashMap
obsługuje klucze o wartości null specjalnie (ponieważ nie może wywołać.hashCode()
obiektu zerowego), ale wartości null nie są niczym specjalnym, są przechowywane na mapie jak wszystko inneźródło
HashMap
(putForNullKey
), która to obsługuje; przechowuje to w tabeli 0B val = foo.containsKey(search) ? foo.get(search) : foo.get(null);
Myślę, że możemy po prostu wywołać metodę get na kluczu wyszukiwania, co da ten sam wynik.B val = foo.get(search);
czy mógłbyś mnie poprawić, jeśli coś jest nie tak?val
na,null
jeśli klucz nie istnieje; mój ustawia go na dowolnenull
mapy na mapie. O to właśnie chodziło, zapisuję domyślną wartość niezerową podnull
kluczem w mapie i używam jej, jeśli rzeczywisty klucz nie istniejeJednym z przykładów może być modelowanie drzew. Jeśli używasz HashMap do reprezentowania struktury drzewa, gdzie klucz jest elementem nadrzędnym, a wartością jest lista dzieci, wówczas wartościami
null
klucza byłyby węzły główne.źródło
Jednym z przykładów użycia
null
wartości jest użycieHashMap
jako pamięci podręcznej wyników kosztownej operacji (takiej jak wywołanie zewnętrznej usługi sieciowej), która może powrócićnull
.Umieszczenie
null
wartości na mapie pozwala następnie na rozróżnienie między przypadkiem, w którym operacja nie została wykonana dla danego klucza (cache.containsKey(someKey)
zwracafalse
), a gdzie operacja została wykonana, ale zwróciłanull
wartość (cache.containsKey(someKey)
zwracatrue
,cache.get(someKey)
zwracanull
).Bez
null
wartości należałoby albo umieścić w pamięci podręcznej jakąś specjalną wartość, aby wskazaćnull
odpowiedź, albo po prostu w ogóle nie buforować tej odpowiedzi i wykonywać operację za każdym razem.źródło
Dotychczasowe odpowiedzi uwzględniają tylko wartość posiadania
null
klucza, ale pytanie dotyczy równieżany number of null values
.Korzyści płynące z przechowywania wartości
null
w kluczu w HashMap są takie same jak w bazach danych itp. - można zapisać rozróżnienie między wartością, która jest pusta (np. Ciąg „”), a brakiem wartości w ogóle (null) .źródło
Oto mój jedyny nieco wymyślony przykład przypadku, w którym
null
klucz może być przydatny:public class Timer { private static final Logger LOG = Logger.getLogger(Timer.class); private static final Map<String, Long> START_TIMES = new HashMap<String, Long>(); public static synchronized void start() { long now = System.currentTimeMillis(); if (START_TIMES.containsKey(null)) { LOG.warn("Anonymous timer was started twice without being stopped; previous timer has run for " + (now - START_TIMES.get(null).longValue()) +"ms"); } START_TIMES.put(null, now); } public static synchronized long stop() { if (! START_TIMES.containsKey(null)) { return 0; } return printTimer("Anonymous", START_TIMES.remove(null), System.currentTimeMillis()); } public static synchronized void start(String name) { long now = System.currentTimeMillis(); if (START_TIMES.containsKey(name)) { LOG.warn(name + " timer was started twice without being stopped; previous timer has run for " + (now - START_TIMES.get(name).longValue()) +"ms"); } START_TIMES.put(name, now); } public static synchronized long stop(String name) { if (! START_TIMES.containsKey(name)) { return 0; } return printTimer(name, START_TIMES.remove(name), System.currentTimeMillis()); } private static long printTimer(String name, long start, long end) { LOG.info(name + " timer ran for " + (end - start) + "ms"); return end - start; } }
źródło
throw Exception
. Poza tym to nie jest tak, że próba zatrzymania nieistniejącego lub już zatrzymanego timera jest czymś, z czego dzwoniący może ogólnie odzyskać.Inny przykład: używam go do grupowania danych według daty. Ale niektóre dane nie mają daty. Mogę to zgrupować z nagłówkiem „NoDate”
źródło
Klucz pusty może być również pomocny, gdy mapa przechowuje dane dla wyborów interfejsu użytkownika, w których klucz mapy reprezentuje pole fasoli.
Odpowiednia wartość pola zerowego byłaby na przykład reprezentowana jako „(proszę wybrać)” w wyborze interfejsu użytkownika.
źródło