Javaの[java.util.Map]において、あるキーにnullを代入する場合と、そのキーに何も代入しない場合では振る舞いが異なるようなケースがある
その中でも最も身近な存在なのが[Map.containsKey(key)]だと思う。
プログラム例: Snippet.java
public class Snippet { public static void main(String... args) { Map<String, String> map = new HashMap<>(); map.put("hoge", "fuga"); map.put("piyo", null); System.out.println("map.containsKey(\"hoge\") = " + map.containsKey("hoge")); System.out.println("map.containsKey(\"piyo\") = " + map.containsKey("piyo")); System.out.println("map.containsKey(\"piyopiyo\") = " + map.containsKey("piyopiyo")); System.out.println("map.get(\"hoge\") = " + Optional.ofNullable(map.get("hoge")).orElse("null")); System.out.println("map.get(\"piyo\") = " + Optional.ofNullable(map.get("piyo")).orElse("null")); System.out.println("map.get(\"piyopiyo\") = " + Optional.ofNullable(map.get("piyopiyo")).orElse("null")); } }
実行結果: Snippet.java
map.containsKey("hoge") = true map.containsKey("piyo") = true map.containsKey("piyopiyo") = false map.get("hoge") = fuga map.get("piyo") = null map.get("piyopiyo") = null
結論から言ってしまうと、valueをnullとして[Map.put(key, value)]した場合は、キーの情報は([Map.keySet()]の結果のSet)それが残る。
[Map.containsKey(key)]はキーが存在しているかどうかをチェックする関数なので、値がnullであってもキーが存在しているとなってしまう。
上記の例では[piyo]も[piyopiyo]も[map.get(key)]で取得できる値はnullで変わりないが、[map.containsKey(key)]の結果が異なっている。
[Map.containsKey(key)]だけで要素の存在判定をしているような場合は[NullPointerException]を招く可能性があるので注意が必要。
ちなみに、キーの存在を消したい場合には[Map.remove(key)]を使用する。