2010-05-31 3 views
73

HashMap pozwala na jeden pusty klucz i dowolną liczbę wartości pustych. Jaki jest tego pożytek?Jaki jest pożytek z dodania pustego klucza lub wartości do HashMap w Javie?

+11

"Być może problemem nie jest to, że nic nam nie przeszkadza, ale że zawracamy sobie tym głowę." – bmargulies

+3

W Guava, kolekcje google, wiele klas nie dopuszcza wartości NULL, a uzasadnienie jest takie, że 95% przypadków nie wymaga wartości null i mogą one stanowić błędy, potencjalnie trudne do znalezienia. – stivlo

+0

Dziwne jest to, że 'ConcurrentHashMap' nie obsługuje kluczy null, podczas gdy' HashMap' działa. – codepleb

Odpowiedz

106

Nie jestem pewien, o co prosisz, ale jeśli szukasz przykładu, kiedy chciałbyś użyć klucza zerowego, często używam ich na mapach do reprezentowania przypadku domyślnego (tj. Wartości które powinny być stosowane, jeżeli dany klucz nie jest obecny):

Map<A, B> foo; 
A search; 
B val = foo.containsKey(search) ? foo.get(search) : foo.get(null); 

HashMap obsługuje klucze zerowe specjalnie (ponieważ nie można nazwać .hashCode() na null obiektu), ale wartości null nie są niczym specjalnym, ale jest przechowywany na mapie, jak wszystko inne.

+3

Więc jeśli .hashCode() nie jest możliwe w przypadku wartości null, która decyduje, do którego karetki zostanie wprowadzony klucz zerowy? – Pacerier

+22

@Pacerier Jest specjalna metoda w 'HashMap' (' putForNullKey'), która ją obsługuje; przechowuje ją w tabeli 0 –

+0

@MichaelMrozek twoja ostatnia linia 'B val = foo.containsKey (szukaj)? foo.get (search): foo.get (null); ' Myślę, że możemy po prostu wywołać metodę get na kluczu wyszukiwania, który będzie miał ten sam wynik. 'B val = foo.get (szukaj);' czy możesz mnie poprawić, jeśli coś złego się dzieje? – dheerajraaj

25

Jednym z przykładów jest modelowanie drzew. Jeśli używasz HashMap do reprezentowania struktury drzewa, gdzie klucz jest elementem nadrzędnym, a wartość jest listą elementów podrzędnych, wówczas wartościami dla klucza null będą węzły główne.

2

Oto mój tylko-nieco-wymyślony przykład przypadku, gdy klucz null mogą być przydatne:

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; 
    } 
} 
+0

Jeśli próbujesz zatrzymać nieistniejący timer, lub który został zatrzymany już, to powinien być błąd, a nie ignorowany. –

+0

@QPaysTaxes - Zależy od twojego zamiaru. Jeśli potrzebujesz lekkiego narzędzia, które można łatwo wykorzystać, zazwyczaj nie chcesz "rzucać wyjątków". Poza tym nie jest tak, że próba zatrzymania nieistniejącego lub już zatrzymanego timera jest czymś, z czego osoba dzwoniąca może ogólnie wyzdrowieć. – aroth

1

Inny przykład: Używam go do grupy danych według daty. Ale niektóre dane nie mają daty. Mogę zgrupować go z nagłówkiem "NoDate"

3

Dotychczasowe odpowiedzi uwzględniają tylko wartość klucza o numerze null, ale pytanie dotyczy również pytania o numer any number of null values.

Zaleta polegająca na zapisywaniu wartości null w stosunku do klucza w HashMapie jest taka sama jak w bazach danych, itp. - można zapisać rozróżnienie między wartością pustą (np. Ciąg "") i brakiem wartości w ogóle (null).

6

Przykładem wykorzystania dla nullwartości jest, gdy za pomocą HashMap jako pamięć podręczna dla wyników drogich operacji (na przykład do połączenia z zewnętrznym usług internetowych), które mogą powrócić null.

Umieszczenie wartości null na mapie, a następnie pozwala odróżnić przypadku, gdy operacja nie została wykonana dla danego klucza (cache.containsKey(someKey) powraca false) i gdzie praca została wykonana, ale wrócił wartość null (cache.containsKey(someKey) zwraca true, cache.get(someKey) zwraca null).

Bez wartości null należy wprowadzić wartość specjalną w pamięci podręcznej, aby wskazać odpowiedź null lub po prostu nie buforować tej odpowiedzi i wykonać operację za każdym razem.

0

Klucz zerowy może być również przydatny, gdy mapa zapisuje dane dla wyborów interfejsu użytkownika, w których klucz mapy reprezentuje pole fasoli.

Odpowiednia wartość pola zerowego będzie na przykład reprezentowana jako "(proszę wybrać)" w wyborze interfejsu użytkownika.

Powiązane problemy