web-dev-qa-db-ja.com

HashSetはどのように重複を許可しませんか?

addHashSetメソッドを試していました。それが言及されている

このセットにすでに要素が含まれている場合、呼び出しはセットを変更せずにfalseを返します。

しかし、addメソッドは内部的にHashMapの値を保存しています

public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}

putHashMapメソッドは、

指定された値をこのマップの指定されたキーに関連付けます。マップに以前にキーのマッピングが含まれていた場合、古い値は置き換えられます。

つまり、putHashMapメソッドが古い値を置き換える場合、HashSetaddメソッドは、要素が重複する場合にセットを変更しないままにする方法?

32
Zeeshan

PRESENTは単なるダミー値です。セットは実際にはそれを気にしません。セットdoesが気にするのは、マップのkeysです。したがって、ロジックは次のようになります。

Set.add(a):
  map.put(a, PRESENT) // so far, this is just what you said
    the key "a" is in the map, so...
      keep the "a" key, but map its value to the PRESENT we just passed in
      also, return the old value (which we'll call OLD)
  look at the return value: it's OLD, != null. So return false.

さて、OLD == PRESENTは重要ではありません。また、Map.putはキーを変更せず、そのキーにマップされた値だけを変更することに注意してください。マップのkeysSetが本当に気にするものなので、Setは変わりません。

実際、​​hasSetの基本構造に何らかの変更がありました-(a, OLD)のマッピングを(a, PRESENT)に置き換えました。しかし、それはSetの実装の外側からは観察できません。 (そして、たまたま、OLD == PRESENTなので、その変更は本当の変更ではありません。).

32
yshavit

ご覧のとおり、HashSet.addメソッドは、値としてではなくキーとしてHashMap.putに要素を追加します。値はキーではなくHashMapで置き換えられます。

5
shazin

見る - HashMap#put

指定された値をこのマップの指定されたキーに関連付けます。マップに以前にキーのマッピングが含まれていた場合、古い値は置き換えられます。

キーをnew値に置き換えます。これにより、HashSetに重複がなくなります。

3
Maroun
public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}

eがキーであるため、eがすでに存在する場合、putnullを返しません。したがって、addはfalseを返します。

putのJavaDoc:

キーに関連付けられた以前の値、またはキーのマッピングがなかった場合はnull (nullの戻り値は、マップが以前にnullをキーに関連付けていたことを示す場合もあります。)

2
Batty

HashMap.put()のjavadocsから、「指定された値をこのマップの指定されたキーに関連付けます。マップに以前にキーのマッピングが含まれていた場合、古い値は置き換えられます。」

したがって、マップ値が置き換えられ(HashSetクラスの定数静的フィールドであるため、同じインスタンスが置き換えられます)、マップキーはそのまま保持されます(実際にはIS Setコレクションアイテム)

1
sutanu dalui