web-dev-qa-db-ja.com

ハッシュマップにnull値またはnullキーがあると便利なのはなぜですか?

Hashtableはnullキーまたは値を許可しませんが、HashMapはnull値と1つのnullキーを許可します。

質問:

  1. これはなぜですか?
  2. このようなキーと値をHashMapに持つとどのように役立ちますか?
29
sab

1.なぜそうなのですか?

HashMapはHashtableよりも新しく、いくつかの制限が修正されています。

私はデザイナーが何を考えていたかしか推測できませんが、ここに私の推測があります:

  • Hashtableは、各キーに対して hashCode を呼び出すことにより、各キーのハッシュを計算します。キーがnullの場合、これは失敗するため、これがnullをキーとして許可しない理由になる可能性があります。
  • キーが存在しない場合、メソッド Hashtable.get はnullを返します。 nullが有効な値である場合、nullがキーは存在するが値nullを持っていることを意味するのか、またはキーが存在しないのかはあいまいです。あいまいさは悪いので、これがnullを値として許可しない理由になる可能性があります。

ただし、実際にはnullを格納したい場合があるため、HashMapで制限が削除されたことがわかります。次の警告も HashMap.get のドキュメントに含まれていました。

Nullの戻り値は、マップがキーのマッピングを含まないことを必ずしも示すわけではありません。マップがキーをnullに明示的にマップすることも可能です。


2.そのようなキーと値をHashMapに持つとどのように役立ちますか?

あなたが知っている存在するが関連付けられた値を持たないキーと存在しないキーを区別するために、明示的にnullを格納すると便利です。例は、登録済みユーザーとその誕生日のリストです。特定のユーザーの誕生日を尋ねる場合は、そのユーザーが存在しないユーザーと既存のユーザーを区別できるようにする必要がありますが、ユーザーは誕生日を入力していません。

Nullをキーとして保存したい(良い)理由は考えられません。一般的にはnullをキーとして使用しないことをお勧めしますが、おそらく、ヌル。

43
Mark Byers

まあ、私はマーク・バイアーズが完全に答えたと思うので、null値とキーが役立つ単純な例だけです:

同じ入力に対して常に同じ結果を返す高価な関数があるとします。マップは、その結果をキャッシュする簡単な方法です。場合によっては関数がnullを返すことがありますが、実行に負荷がかかるため、とにかく保存する必要があります。したがって、null値を格納する必要があります。関数の入力として受け入れられる場合、同じことがnullキーにも当てはまります。

14
sinuhepop

HashTableはJDK 1.0からの非常に古いクラスです。JDK 1.から配置されたクラスはLegacyクラスと呼ばれ、デフォルトでは同期です。 。

これを理解するには、まず、このクラスに著者が書いたコメントを理解する必要があります。 「このクラスは、キーを値にマップするハッシュテーブルを実装しています。 null以外のオブジェクトは、キーまたは値として使用できます。ハッシュテーブルからオブジェクトを正常に保存および取得するには、キーとして使用されるオブジェクトにhashCodeメソッドとequalsメソッドを実装する必要があります。」

HashTableクラスはハッシュメカニズムに実装されており、キーと値のペア、つまりキーオブジェクトに必要なハッシュコードを格納します。 HashTableは、各キーでhashCodeを呼び出すことにより、各キーのハッシュを計算します。これは失敗します。キーがnullの場合、nullキーのハッシュを与えることができず、NullPointerExceptionがスローされます。値の場合も同様で、値がnullの場合はnullをスローします

しかし、後になってnullキーと値には独自の重要性があることがわかり、1つのnullキーと複数のnull値を許可するHashMapのように、HashTableの改訂された実装が導入されました。

HashMapの場合、1つのnullキーを許可し、キーのnullチェックがあります。キーがnullの場合、その要素はエントリ配列のゼロの場所に格納されます。

Keys are uniqueは1つのNullキーのみであり、多くのNull値が許可されるため、HashMapに複数のNullキーを含めることはできません。

[〜#〜] use [〜#〜]-デフォルト値に使用できるヌルキー。

HashTableの変更されたより良い実装は、後にConcurrentHashMapとして導入されました。

3
shubham malik

Mark Ba​​yersの回答に加えて、Nullはデータと見なされ、さらにチェックするための値として格納する必要があります。多くの場合、値としてnullを使用して、キーエントリが存在するかどうかを確認できますが、値が割り当てられていないため、それに応じてアクションを実行できます。これは、最初にキーが存在するかどうかを確認し、次に値を取得することで実行できます。何のデータも(チェックなしで)置くだけの場合がもう1つあります。取得後、すべてのチェックが適用されます。

キーとしてnullであるのに対し、デフォルトのデータを定義するために使用できると思います。通常、キーとしてnullを指定してもあまり意味がありません。

2
Amit Agrawal

HashMap卿はまた、HashMapに要素を挿入するために内部的にhashCode()メソッドを使用しているので、これは「HashTableがnullキーを許可する理由」の適切な理由ではないと思います

1
user3207104

これにより、Mapインターフェースが使いやすくなります。 nullは、参照型の正当な値です。マップでnullキーと値を処理できるようにすると、APIを呼び出す前にnullチェックを行う必要がなくなります。そのため、マップAPIは実行時に作成する「驚き」を減らします。

たとえば、mapは、単一のフィールドに基づいて同種のオブジェクトのコレクションを分類するために使用されることが一般的です。マップがnullと互換性がある場合、コードはifステートメントのない単純なループであるため、より簡潔になります(もちろん、コレクションにnull要素がないことを確認する必要があります)。分岐/例外処理のないコード行が少ないほど、論理的に正しい可能性が高くなります。

一方、nullを許可しないと、マップインターフェイスがより使いやすく/安全/使いやすくなります。 nullを拒否するためにマップに依存することは実用的ではありません。つまり、例外がスローされ、キャッチして処理する必要があります。または、例外を取り除くために、マップメソッドを呼び出す前にnullが何もないことを確認する必要があります。この場合、入力をフィルタリングしたため、マップがnullを受け入れてもかまいません。

0
Xinchao