JavaのHashMapにnullキーまたは値を追加する用途は何ですか?


91

HashMapでは、1つのnullキーと任意の数のnull値を使用できます。それの用途は何ですか?


11
「おそらく問題は、何も私たちを悩ませているということではなく、私たちがそれを悩ませていることです。」
bmargulies 2010年

3
グアバ、グーグルコレクションでは、多くのクラスがnullを許可していません。その背後にある理由は、ケースの95%がnullを必要とせず、バグを表す可能性があり、見つけにくい場合があるためです。
stivlo

奇妙なことに、ConcurrentHashMapnullキーはサポートされていませんが、サポートされていますHashMap
codepleb 2016年

2
HashMapだけがnullを許可します:)
subhashis

回答:


126

私はあなたが何を求めているかについては肯定的ではありませんが、nullキーを使用したい場合の例を探している場合は、デフォルトのケース(つまり、使用する値)を表すためにマップでよく使用します指定されたキーが存在しない場合):

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

HashMapnullキーを特別に処理します(.hashCode()nullオブジェクトを呼び出すことができないため)が、null値は特別なものではなく、他のようにマップに格納されます


4
では、.hashCode()がnullで不可能である場合、nullキーを入力するキャリッジを決定するのは誰ですか?
パセリエ

26
@Pacerier HashMapputForNullKey)にはそれを処理する特別なメソッドがあります。それをテーブル0に保存します
Michael Mrozek

1
@MichaelMrozek最後の行B val = foo.containsKey(search) ? foo.get(search) : foo.get(null);私は、同じ結果になる検索キーでgetメソッドを呼び出すだけでよいと思います。 B val = foo.get(search);何か問題が発生した場合、私を訂正していただけませんか?
dheerajraaj 2017

6
@ dheeraj92 キーが存在しない場合、コードはに設定さvalnullます。私はそれをnullマップ内のどのマップにも設定します。それがポイントでした、私はデフォルトの非null値をnullマップのキーに格納し、実際のキーが存在しない場合はそれを使用します
Michael Mrozek

28

1つの例は、木のモデリングです。キーが親で値が子のリストであるツリー構造を表すためにHashMapを使用している場合、キーの値はnullルートノードになります。


6

null の使用例の1つは、をHashMap返す可能性のある負荷の高い操作(外部Webサービスの呼び出しなど)の結果のキャッシュとしてを使用する場合nullです。

nullマップに値を置くと、特定のキーに対して操作が実行されなかった場合(cache.containsKey(someKey)returns false)と、操作は実行されたがnull値をcache.containsKey(someKey)返した場合(returns truecache.get(someKey)returns null)を区別できます。

null値がない場合、null応答を示すためにキャッシュに特別な値を入れるか、単にその応答をまったくキャッシュせずに毎回操作を実行する必要があります。


3

これまでの回答では、nullキーの価値だけを考慮していましたが、質問ではについても尋ねていany number of null valuesます。

nullHashMapのキーに対して値を格納することの利点は、データベースなどと同じです。空の値(たとえば、文字列 "")とまったく値がない(null)との違いを記録できます。 。


2

これは、nullキーが役立つ可能性があるケースの、私のわずかに工夫された唯一の例です。

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

存在しないタイマー、または既に停止されているタイマーを停止しようとすると、エラーではなく、無視されません。
ファンドモニカの訴訟

@QPaysTaxes-あなたの意図に依存します。簡単に使用できる軽量のユーティリティが必要な場合、一般的には不要ですthrow Exception。その上、それは存在しないかすでに停止されたタイマーを止めようとする試みが一般に呼び出し者が回復することができるものであるようではありません。
2015

1

別の例:データを日付でグループ化するために使用します。ただし、一部のデータには日付がありません。ヘッダー「NoDate」でグループ化できます


0

nullキーは、マップがBeanフィールドを表すUI選択のデータをマップに格納する場合にも役立ちます。

たとえば、対応するnullフィールド値は、UI選択で「(選択してください)」として表されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.