web-dev-qa-db-ja.com

ConcurrentHashMap putIfAbsent()がnullを返しています

次のプログラムはNULLを出力しています。理由がわかりません。

public class ConcurrentHashMapTest {
    public static final ConcurrentMap<String, String> map = new ConcurrentHashMap<>(5, 0.9f, 2);

    public static void main(String[] args) {
        map.putIfAbsent("key 1", "value 1");
        map.putIfAbsent("key 2", "value 2");

        String value = get("key 3");
        System.out.println("value for key 3 --> " + value);
    }

    private static String get(final String key) {
        return map.putIfAbsent(key, "value 3");
    }
}

誰かが私が行動を理解するのを手伝ってもらえますか?

20
Niranjan

ConcurrentMap.putIfAbscentは、指定されたキーに関連付けられた以前の値を返します。キーのマッピングがなかった場合はnullを返します。 「キー3」に関連付けられた値がありませんでした。すべて正しい

23

問題は、定義上、putIfAbsent新しい値ではなく古い値を返すことです(存在しない場合の古い値は常にnullです)。 computeIfAbsentを使用します-これにより、新しい値が返されます。

private static String get(final String key) {
    return map.computeIfAbsent(key, s -> "value 3");
}
16
Ondřej Stašek

putIfAbsent() は、指定されたキーに関連付けられた以前の値を返します。キーのマッピングがなく、_key 3_が存在しないため、nullマップ内でnullを返すようにします。

マップに_key 1_と_key 2_を追加しましたが、_key 3_はどの値にも関連付けられていません。したがって、nullを取得します。 _key 3_を何らかの値でマップすると、putIfAbsent()はそのキーに関連付けられた以前の値を返します。

マップに値Aに関連付けられた_key 3_がすでに含まれている場合のように

_key 3 ---> A
_

次に、map.putIfAbsent("key 3","B")を呼び出すとAが返されます

7
Narendra Pathai

これはよくある質問であり、おそらくこの動作が直感的でないことを示唆しています。おそらく混乱は、dict.setdefault()がpythonおよび他の言語で機能する方法に起因します。配置した同じオブジェクトを返すと、コードの数行を削減するのに役立ちます。

考えてみましょう:

if (map.contains(value)){
    obj = map.get(key);
}
else{
    obj = new Object();
}

対:

obj = map.putIfAbsent(key, new Object());
5

Javadocにあります:

指定されたキーに関連付けられた以前の値を返します。キーのマッピングがなかった場合はnullを返します

4
Bozho

ConcurrentHashMap.putIfAbsent のドキュメントをお読みください:

返品
指定されたキーに関連付けられた以前の値、またはキーのマッピングがなかった場合はnull

キー"key 3"には以前の値がなかったため、nullを返します。

3
Mark Rotteveel

ドキュメントを見ると、

戻り値:
指定されたキーに関連付けられた前の値、またはキーのマッピングがなかった場合はnull

あなたの場合、以前はキーに値が関連付けられていなかったため、NULL

2
Ankur Shanbhag