私はこのコードをJavaで持っているとしましょう:
_HashSet<String> wordSet = new HashSet<String>();
String a = "hello";
String b = "hello";
wordSet.add(a);
_
wordSet.contains(b);
はtrue
またはfalse
を返しますか?私が理解したことから、a
とb
は、それらの値が同じであっても異なるオブジェクトを参照します。したがって、contains()
はfalse
を返す必要があります。ただし、このコードを実行すると、true
が返されます。 true
が値_"hello"
_を含む限り、Stringオブジェクトb
がどこから来ても、常にb
を返しますか?これは保証されますか?常に?そうでない場合、いつこれが保証されないのですか?そして、文字列以外のオブジェクトで同様のことをしたい場合はどうなりますか?
equals()
を使用してデータを比較します。以下は Setのjavadoc
セットに要素e2が含まれない場合(e == null?e2 == null:e.equals(e2))に、指定された要素eをこのセットに追加します。
Stringのequals()
メソッドは、文字ごとの比較を行います。 Stringのjavadoc から
引数がnullではなく、このオブジェクトと同じ文字シーケンスを表すStringオブジェクトである場合にのみ、結果はtrueです
実際、HashSetはneitherを実行します。
その実装はHashMapを使用します。セットcontains()
(実際にはHashMapのgetEntry()メソッド内にあるかどうか)を決定する関連コードは次のとおりです。
_if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k))))
_
どれ:
equals()
がtrueを返します答えは「はい」です。wordSet.contains(b)
は常にtrue
を返します
2つのこと:
等しいかどうかを判断するためにequals()メソッドを呼び出さない限り、セットはほとんど役に立ちません。 wordset.contains(b)は、a.equals(b)== trueであるため、trueを返します。
Aとbが異なるオブジェクトを指していることを完全に確信することはできません。詳細については、String.intern()を確認してください。
実際、Javaの文字列リテラルは自動的にインターンされるため、aとbは同じオブジェクトを参照します。
最終的に、contains
は、containsメソッドのオブジェクトID検証ではなく、equals
メソッドをチェックします。したがって、equals
メソッドはcontains
呼び出しに対して呼び出されます。これは、contains
メソッドの呼び出し構造です。
private transient HashMap<E,Object> map;
public boolean contains(Object o) {
return map.containsKey(o);
}
public boolean containsKey(Object key) {
return getEntry(key) != null;
}
final Entry<K,V> getEntry(Object key) {
int hash = (key == null) ? 0 : hash(key.hashCode());
for (Entry<K,V> e = table[indexFor(hash, table.length)];
e != null;
e = e.next) {
Object k;
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
}
return null;
}
平等。あなたの例では、HashSetはcontains()
をチェックするため、a.equals( b )
はtrueを返します。