154

の JavaDoc にConcurrentHashMapは次のように書かれています。

と同様Hashtableですが、このクラスとは異なりHashMap、このクラスをキーまたは値として使用することはできません。null

私の質問: なぜですか?

Hashtable2 番目の質問: null を許可しないのはなぜですか?

データを格納するために多くの HashMaps を使用しました。しかし、に変更するConcurrentHashMapと、NullPointerExceptions のために何度か問題が発生しました。

4

7 に答える 7

234

ConcurrentHashMap自身の著者(Doug Lea) より:

ConcurrentMaps (ConcurrentHashMaps、ConcurrentSkipListMaps) で null が許可されない主な理由は、非同時マップではほとんど許容できないあいまいさに対応できないためです。主なものは、 if map.get(key)returnsnullの場合、キーが明示的にマップされているかどうか、キーがマップされていないかどうかを検出できないことですnull。非同時マップでは、これを map.contains(key)で確認できますが、同時マップでは、呼び出し間でマップが変更されている可能性があります。

于 2012-02-15T17:23:02.020 に答える
51

少なくとも部分的には、結合して単一の呼び出しにできるようにするためだと思いcontainsKeyますget。マップが null を保持できる場合、getその値のキーがなかったため、または値が null だったために が null を返すかどうかを判断する方法はありません。

なぜそれが問題なのですか?自分でそれを行う安全な方法がないからです。次のコードを使用します。

if (m.containsKey(k)) {
   return m.get(k);
} else {
   throw new KeyNotPresentException();
}

は並行マップであるため、との呼び出しmの間でキー k が削除される可能性があり、このスニペットは目的の ではなく、テーブルに存在しなかった null を返します。containsKeygetKeyNotPresentException

通常は、同期することで解決しますが、同時実行マップではもちろん機能しません。したがって、 の署名getを変更する必要があり、下位互換性のある方法でそれを行う唯一の方法は、ユーザーが最初に null 値を挿入するのを防ぎ、それを「キーが見つかりません」のプレースホルダーとして引き続き使用することでした。

于 2011-01-21T13:26:16.760 に答える
3

null で同期することはできません。

編集:この場合、これが正確な理由ではありません。私は当初、同時更新に対して何かをロックしたり、何かが変更されたかどうかを検出するためにオブジェクト モニターを使用したりすることで何か凝ったことが起こっていると思っていましたが、ソース コードを調べると、私が間違っていたようです。ハッシュのビットマスク。

その場合、彼らは Hashtable をコピーするためにそれを行ったのではないかと思います。リレーショナル データベースの世界では null != null であるため、キーとして null を使用しても意味がありません。

于 2009-03-30T19:18:16.180 に答える
0

ConcurrentHashMap はスレッドセーフです。null キーと null 値を許可しないことは、スレッドセーフであることを確認するための一部だったと思います。

于 2009-03-30T19:17:01.393 に答える
0

API ドキュメントの次のスニペットが良いヒントを与えてくれると思います。

ConcurrentHashMap彼らはおそらく、完全に互換性/交換可能にしたかっただけHashtableです。そして、Hashtablenull キーと値を許可しないように..

于 2009-03-30T19:29:01.707 に答える
-3

null 値を許可しないことは正しいオプションではないと思います。多くの場合、null 値を持つキーを並行マップに配置したいと考えています。しかし、ConcurrentHashMap を使用すると、それができなくなります。JDK の今後のバージョンがそれをサポートできることをお勧めします。

于 2019-01-08T09:43:05.213 に答える