web-dev-qa-db-ja.com

HashSet / HashMapに重複した値を追加して前の値を置き換えますか

以下のコードを検討してください。

HashSet hs = new HashSet();
hs.add("hi"); -- (1)
hs.add("hi"); -- (2)

HashSetは重複を許可しないので、hs.size()は1を与え、1つの要素だけが格納されます。

重複した要素を追加するのかどうか、それが前の要素を置き換えるのか、それとも単に追加しないのかを知りたいのですが。

また、同じ場合にHashMapを使用するとどうなりますか?

121
Anand

HashMap の場合は、古い値を新しい値に置き換えます。

HashSet の場合、項目は挿入されません。

215
Keppil

最初に知っておく必要があるのは、HashSetSetのように振る舞うということです。つまり、あなたはオブジェクトを直接HashSetに追加し、重複を含むことはできません。値を直接HashSetに直接追加するだけです。

ただし、HashMapMap型です。つまり、エントリを追加するたびに、キーと値のペアが追加されます。

HashMapでは、重複した値を持つことはできますが、重複するキーを持つことはできません。 HashMapでは、新しいエントリが古いエントリを置き換えます。最新のエントリはHashMapにあります。

HashMapとHashSetの間のリンクを理解する:

HashMapは重複キーを持つことができません。舞台裏でHashSetHashMapを使います。

任意のオブジェクトをHashSetに追加しようとすると、このエントリは実際にはHashMapのキーとして格納されます - HashMapの裏で使用されるものと同じHashSet。この基礎となるHashMapはキーと値のペアを必要とするため、ダミーの値が生成されます。

同じHashSetに別の複製オブジェクトを挿入しようとすると、その下にあるHashMapにキーとしてそれを挿入しようとします。ただし、HashMapは重複をサポートしません。したがって、HashSetは、その型の値を1つだけ持つことになります。副次的な注意として、重複するキーごとに、HashSetのエントリに対して生成された値はランダムまたはダミーの値なので、キーはまったく置き換えられません。キーを削除して同じキー(ダミーの値は同じ)を追加してもまったく意味がないため、無視されます。

要約:

HashMapでは、valuesを重複させることができますが、keysはできません。 HashSetに重複を含めることはできません。

オブジェクトの追加が正常に完了したかどうかを確認するには、.add()を呼び出したときに返されるbooleanの値を確認し、それがtrueまたはfalseを返すかどうかを確認します。 trueが返された場合は挿入されました。

42
Jimmy

docs はこれに関してはっきりしています:HashSet.addを置き換えません:

指定された要素がまだ存在しない場合は、このセットに追加します。より正式には、(e == null?e2 == null:e.equals(e2))のように、このセットに要素e2が含まれていない場合は、指定された要素eをこのセットに追加します。 このセットにすでに要素が含まれている場合、呼び出しはそのセットを変更せずにfalseを返します。

しかし HashMap.putを置き換えます。

マップに以前にキーのマッピングが含まれていた場合は、古い値が置き換えられます。

17
pb2q

HashSetの場合は、置き換えられません。

ドキュメントから:

http://docs.Oracle.com/javase/6/docs/api/Java/util/HashSet.html#add(E

"指定された要素がまだ存在しない場合、このセットに追加します。より正式には、このセットに要素e2が含まれていない場合、指定された要素eをこのセットに追加します。(e == null?e2 == null:e.equals(このセットにすでに要素が含まれている場合、呼び出しはそのセットを変更せずにfalseを返します。 "

4
Bob Provencher

私が間違っている場合でも訂正してください、しかしあなたが得ているのは文字列で、 "Hi" == "Hi"が必ずしも正しいというわけではないということです(必ずしも同じオブジェクトではないので)。

1という答えが得られるのは、JVMが可能な場合は文字列オブジェクトを再利用するためです。この場合、JVMは文字列オブジェクトを再利用しているため、Hashmap/Hashset内の項目を上書きしています。

しかし、この動作は保証されていません(同じ値 "Hi"を持つ異なる文字列オブジェクトになる可能性があるため)。表示される動作は、JVMの最適化によるものです。

1
Nick Rippe

別の言い方をすれば、キーがすでに存在するHashMapにキーと値のペアを挿入すると(ある意味ではhashvalue()は同じ値を与えますが、und equal()は真ですが、2つのオブジェクトはいくつかの点で異なります。キーは置き換えられませんが、値は上書きされます。このキーは単にhashvalue()を取得し、それを使ってテーブル内の値を見つけるために使用されます。 HashSetはHashMapのキーを使用し、結果として(ユーザにとって)重要ではない任意の値を設定するので、セットの要素も置き換えられません。

0
Marco Rothley

HashMap基本的にはEntryが含まれ、その後にKey(Object)Value(Object)が含まれます内部的にはHashSetHashMapHashMapは既にあなたが指摘したように値を置き換えます。それは本当にキーを置き換えます???いいえ..そしてそれがここでのトリックです。 HashMapは基になるHashMapのキーとしてその値を保持し、valueは単なるダミーオブジェクトです。HashMapに同じ値を再挿入しようとした場合(基になるMapのキー)。ダミーの値を置き換えます。キー(HashSetの値)ではありません。

以下のHashSetクラスのコードを見てください。

public boolean  [More ...] add(E e) {

   return map.put(e, PRESENT)==null;
}

ここでeはHashSetの値ですが、基礎となるmap.andのキーは置き換えられません。私が混乱を解消できることを願っています。

0
Kunal Kumar

HashSetはHashMapによってバックアップされるので、最初にHashマップのputメソッドをチェックする必要があります。

  1. HashSetに重複した値を追加するときは、文字列 "One"を言います。
  2. エントリ( "one"、PRESENT)がHashmapに挿入されます(setに追加されたすべての値の場合、値は "PRESENT"になります。これはObject型の場合です)。
  3. HashmapはエントリをMapに追加して値を返します。この場合は "PRESENT"、またはEntryがない場合はnullです。
  4. Hashsetのaddメソッドは、Hashmapから返された値がnullに等しい場合はtrueを返し、そうでない場合はfalseを返します。これはエントリがすでに存在することを意味します。
0
shiv