のJavaDoc ConcurrentHashMapはこれを言っています:
と
Hashtableは異なりHashMap、とは異なり、このクラスはキーまたは値として使用できませんnull。
私の質問:なぜですか?
2番目の質問:Hashtablenullを許可しないのはなぜですか?
私はデータを格納するために多くのHashMapを使用しました。しかし、変更するConcurrentHashMapとNullPointerExceptionsが原因で何度か問題が発生しました。
のJavaDoc ConcurrentHashMapはこれを言っています:
と
Hashtableは異なりHashMap、とは異なり、このクラスはキーまたは値として使用できませんnull。
私の質問:なぜですか?
2番目の質問:Hashtablenullを許可しないのはなぜですか?
私はデータを格納するために多くのHashMapを使用しました。しかし、変更するConcurrentHashMapとNullPointerExceptionsが原因で何度か問題が発生しました。
回答:
作者ConcurrentHashMap(ダグ・リー)の作者から:
ConcurrentMaps(ConcurrentHashMaps、ConcurrentSkipListMaps)でnullが許可されない主な理由は、非並行マップではほとんど許容できないあいまい性に対応できないためです。主なものは、を
map.get(key)返す場合null、キーが明示的にマッピングされているかnull、キーがマッピングされていないかを検出できないことです。非並行マップでは、を使用してこれを確認できますが、並行マップでは、map.contains(key)呼び出し間でマップが変更されている可能性があります。
Optional内部で値としてsを使用しない理由
OptionalはJava 8の機能であり、当時は利用できませんでした(Java 5)。Optional確かに、今はsを使用できます。
私は、少なくとも部分的に、1つの通話にまとめて1つの通話にできるようにすることだcontainsKeyと思いますget。マップがnullを保持できる場合、getその値のキーがないため、または単に値がnullだったためにnullが返されているかどうかを判断する方法はありません。
なぜそれが問題なのですか?自分でそれを行う安全な方法がないからです。次のコードを見てください。
if (m.containsKey(k)) {
return m.get(k);
} else {
throw new KeyNotPresentException();
}
以来m同時マップで、キーkが間に削除されてもよいcontainsKeyし、getなく、所望よりも、テーブルではなかったヌルを戻すには、このスニペットを引き起こし、呼KeyNotPresentException。
通常は同期することで解決しますが、並行マップではもちろん機能しません。したがって、の署名はget変更する必要があり、下位互換性のある方法でこれを行う唯一の方法は、ユーザーが最初にnull値を挿入しないようにし、それを「キーが見つかりません」のプレースホルダーとして引き続き使用することでした。
map.getOrDefault(key, NULL_MARKER)。の場合null、値はでしたnull。を返すNULL_MARKER場合、値は存在しませんでした。
Josh Blochが設計しましたHashMap。ダグ・リーが設計しましたConcurrentHashMap。それが名誉なことではないことを願っています。実際、私は、実際のnullが初期化されていないことを表すことができるように、nullはしばしばラッピングを必要とするという問題があると思います。クライアントコードがnullを必要とする場合、null自体をラップする(確かに小さい)コストを支払うことができます。
nullでは同期できません。
編集:これは、この場合の正確な理由ではありません。最初は、同時更新に対して何かをロックしたり、オブジェクトモニターを使用して何かが変更されたかどうかを検出したりするのはおかしいと思っていましたが、ソースコードを調べると間違っていたようです-に基づいた「セグメント」を使用してロックしていますハッシュのビットマスク。
その場合、私は彼らがHashtableをコピーするためにそれをしたのではないかと思います。リレーショナルデータベースの世界ではnull!= nullなので、nullをキーとして使用しても意味がないためです。
APIドキュメントの次のスニペットが良いヒントになると思います:「このクラスは、スレッドの安全性に依存しているが同期の詳細に依存していないプログラムでは、Hashtableと完全に相互運用できます。」
彼らはおそらく、とConcurrentHashMap完全に互換性/交換可能にしたかっただけでしょうHashtable。そしてHashtablenullキーと値を許可しないので。
null値を許可しないことが正しいオプションだとは思いません。多くの場合、null値のキーをコンカレントマップに挿入する必要があります。ただし、ConcurrentHashMapを使用すると、それはできません。今後のバージョンのJDKでサポートできることをお勧めします。