HashSet / HashMapに重複する値を追加すると、以前の値が置き換えられますか


137

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

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

hs.size()HashSet重複を許可しないので1を与えるため、1つの要素のみが保存されます。

重複した要素を追加するかどうかを知りたい場合、前の要素を置き換えますか、それとも単に追加しませんか?

また、HashMap同じケースを使用するとどうなりますか?

回答:


246

の場合HashMap、古い値が新しい値に置き換えられます。

の場合HashSet、アイテムは挿入されません。


1
何が欠けているのかわかりませんが、ソースコードはそうでないことを示しているようです?私は、彼らが裏にチェックをしないことを確認HashMapかどうかを確認するためにkey、すでに呼び出す前に存在しているput裏にmap
mystarrocks 14年

10
@mystarrocks:キーはの要素でありSetput()操作によって置き換えられることはありません。
ケッピル2014年

1
ああ、私は今それを手に入れました。キーがの要素であることを理解しましたが、これはキーではなく値のみをオーバーライドすることにSet気づきましたput()。この場合、それは再びキーの横に置かれた同じ値です。これは、キーが存在するかどうかを確認して置くよりも良い場合とそうでない場合があります。どちらにしても、私はそれがどのように機能するかを理解しています。
mystarrocks 2014年

HashMapとHashSetがなぜそうなるのを好むのか?
Helin Wang 14

@HelinWang:私はそれが計画されたとは思いません、それは単にHashSetの形で実装された効果だと思いますHashMap。ただし、あなたがクラスの開発者の1人でない限り、知ることは困難です。
Keppil、2014

47

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

しかし、HashMapあるMapタイプ。つまり、エントリを追加するたびに、キーと値のペアを追加します。

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

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

覚えておいてください、HashMap重複キーを持つことはできません。舞台裏ではをHashSet使用していHashMapます。

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

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

概要:

HashMap複製valuesは許可しますが、許可しませんkeysHashSet重複を含めることはできません。

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


HashMap allows duplicate valuesHashMapは古い値を新しい値に置き換えます。
Alex78191

20

ドキュメントは、この上のかなりはっきりしている:HashSet.add いない置き換えます。

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

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

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


4

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

ドキュメントから:

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

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


1

私が間違っている場合は修正してください。ただし、文字列では "Hi" == "Hi"が常にtrueになるとは限りません(それらは必ずしも同じオブジェクトではないため)。

ただし、答えが1になるのは、JVMが可能な限り文字列オブジェクトを再利用するためです。この場合、JVMは文字列オブジェクトを再利用しているため、Hashmap / Hashsetのアイテムを上書きしています。

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


0

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

  1. 重複する値を追加すると、HashSetに文字列「One」と言い、
  2. エントリ( "one"、PRESENT)はHashmapに挿入されます(セットに追加されたすべての値について、値は "PRESENT"となり、オブジェクトタイプの場合)
  3. HashmapはエントリをMapに追加し、値を返します。この場合は "PRESENT"です。エントリがない場合はnullです。
  4. Hashsetのaddメソッドは、Hashmapからの戻り値がnullの場合はtrueを返し、それ以外の場合はfalseを返します。これは、エントリがすでに存在することを意味します...

0

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


0

HashMap基本的にはEntryを含みKey(Object)、その後を含み、Value(Object).InternallyでHashSetありHashMapHashMapすでに指摘したように値を置き換えますが、実際にはキーを置き換えますか??? No ..これがここでのトリックです HashMapその値を基になるキーとして保持しHashMap、値は単なるダミーオブジェクトであるため、同じ値をHashMap(基になるマップのキー)に再挿入しようとすると、ダミーの値が置き換えられ、Key(Value for HashSet)は置き換えられません。

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

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

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

ここでeはHashSetの値ですが、基になるマップのキーです。キーは置き換えられません。混乱を解消できるといいのですが。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.