Java'da bir HashMap'e boş anahtar veya değer eklemenin faydası nedir?


91

HashMap, bir boş anahtara ve herhangi bir sayıda boş değere izin verir. Bunun ne faydası var?


11
"Belki de sorun, hiçbir şeyin bizi rahatsız etmemesi değil, bizim onu ​​rahatsız etmemizdir."
bmargulies

3
Guava, google koleksiyonlarında, birçok sınıf boşluğa izin vermez ve bunun arkasındaki mantık, vakaların% 95'inin boşa ihtiyaç duymaması ve bulması potansiyel olarak zor olan hataları temsil edebilmesidir.
stivlo

Garip olan şey, ConcurrentHashMapboş anahtarları desteklemezken desteklemiyor HashMap.
codepleb

2
Yalnızca HashMap
null'a

Yanıtlar:


126

İstediğinizden emin değilim, ancak boş anahtar kullanmak isteyeceğiniz zaman bir örnek arıyorsanız, bunları genellikle haritalarda varsayılan durumu temsil etmek için kullanırım (yani kullanılması gereken değer belirli bir anahtar yoksa):

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

HashMapnull anahtarları özel olarak işler ( .hashCode()boş bir nesnede çağrı yapamayacağı için ), ancak boş değerler özel bir şey değildir, haritada başka herhangi bir şey gibi saklanırlar


4
Öyleyse .hashCode () null üzerinde mümkün değilse, null anahtarın hangi taşıyıcıya gireceğine kim karar verir?
Pacerier

26
@Pacerier HashMap( putForNullKey) 'de onu işleyen özel bir yöntem var; onu tablo 0'da saklar
Michael Mrozek

1
@MichaelMrozek son satırınız B val = foo.containsKey(search) ? foo.get(search) : foo.get(null);Aynı sonuca sahip olan arama tuşu üzerinde basitçe get yöntemini çağırabileceğimizi düşünüyorum. B val = foo.get(search);Bir şeyi yanlış anlarsam lütfen beni düzeltebilir misin?
dheerajraaj

6
@ dheeraj92 Kodunuz koyacaktır valiçin nullanahtar yoksa; benimki onu nullharitadaki haritalara göre ayarlar . Noktasıydı Yani, ben bir varsayılan boş olmayan değeri saklamak nullharitası anahtar ve gerçek anahtar mevcut değilse kullanmak
Michael Mrozek

28

Bir örnek ağaçların modellenmesi olabilir. Anahtarın üst ve değerin alt öğe listesi olduğu bir ağaç yapısını temsil etmek için bir HashMap kullanıyorsanız, anahtarın değerleri nullkök düğümler olacaktır.


6

null Değerlerin kullanımına bir örnek, HashMappahalı bir işlemin (harici bir web hizmetine yapılan çağrı gibi) sonuçları için bir önbellek olarak kullanılmasıdır null.

nullHaritaya bir değer koymak , daha sonra belirli bir anahtar için işlemin gerçekleştirilmediği durumu ( cache.containsKey(someKey)dönüşler false) ve işlemin gerçekleştirildiği ancak bir nulldeğer döndürdüğü ( cache.containsKey(someKey)geri dönüşler true, cache.get(someKey)dönüşler null) durumu ayırt etmenize olanak tanır .

nullDeğerler olmadan , bir nullyanıtı belirtmek için önbelleğe bazı özel değerler koymanız veya bu yanıtı hiç önbelleğe almamalı ve işlemi her seferinde gerçekleştirmeniz gerekir.


3

Şimdiye kadar verilen cevaplar sadece bir nullanahtara sahip olmanın değerini dikkate alıyor , ancak soru aynı zamanda soruyor any number of null values.

Değeri nullbir HashMap'te bir anahtara karşı depolamanın yararı, veritabanlarında olduğu gibi aynıdır - boş bir değere sahip olma (örneğin, dize "") ile hiçbir değere sahip olmama (boş) arasındaki farkı kaydedebilirsiniz. .


2

İşte nullanahtarın yararlı olabileceği bir vakaya dair bir şekilde uydurulmuş tek örneğim :

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

Var olmayan veya zaten durdurulmuş bir zamanlayıcıyı durdurmaya çalışıyorsanız, bu bir hata olmalıdır, göz ardı edilmemelidir.
Fon Monica'nın Davası

@QPaysTaxes - Niyetinize bağlıdır. Kolayca kullanılabilen hafif yarar istiyorsanız, genelde yok etmek istiyor throw Exception'ın etrafında. Ayrıca, var olmayan veya zaten durdurulmuş bir zamanlayıcıyı durdurmaya çalışmak, arayanın genel olarak düzelebileceği bir şey değildir.
aroth

1

Başka bir örnek: Verileri tarihe göre gruplamak için kullanıyorum. Ancak bazı verilerin tarihi yoktur. Bunu "NoDate" başlığı ile gruplayabilirim


0

Boş anahtar, harita anahtarının bir fasulye alanını temsil ettiği kullanıcı arabirimi seçimleri için verileri depoladığında da yararlı olabilir.

Karşılık gelen bir boş alan değeri, örneğin UI seçiminde "(lütfen seçin)" olarak temsil edilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.