Будет ли метод Java HashSet <String> contains() проверять равенство строк или идентификатора объекта?
Скажем, у меня есть этот код в 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
независимо от того, где объект String b
исходит из тех пор, пока b
содержит значение "hello"
? Я всегда это гарантировал? Если нет, когда я не гарантирую это? И что, если бы я хотел сделать что-то подобное с объектами, отличными от строк?
Ответы
Ответ 1
Он использует equals()
для сравнения данных. Ниже приведена javadoc для Set
добавляет указанный элемент e к этому набору, если набор не содержит элемент e2 такой, что (e == null? e2 == null: e.equals(e2)).
Метод equals()
для String делает символ по сравнению с символом. Из javadoc для строки
Результат верен тогда и только тогда, когда аргумент не является нулевым и является объектом String, который представляет ту же последовательность символов, что и этот объект
Ответ 2
На самом деле, HashSet делает ни.
В его реализации используется HashMap, и здесь соответствующий код, определяющий, установлен ли набор contains()
(фактически он внутри метода HashMap getEntry()):
if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k))))
где:
- требует, чтобы хеши были равны, и
- требует либо равенства объекта, либо
equals()
возвращает true
Ответ "да": wordSet.contains(b)
всегда будет возвращать true
Ответ 3
Собственно, и a, и b относятся к одному и тому же объекту, потому что строковые литералы в Java автоматически интернированы.
Ответ 4
Две вещи:
-
Набор был бы бесполезным, если только он не назвал метод equals() для определения равенства. wordset.contains(b) вернет true, поскольку a.equals(b) == true.
-
Вы не можете быть абсолютно уверены, что a и b указывают на разные объекты. Оформить заказ String.intern() для более подробной информации.
Ответ 5
В конечном счете contains
будет проверять метод equals
, а не проверяет его идентификатор объекта для метода contains. Следовательно, метод 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;
}
Ответ 6
Равенство. В вашем примере contains()
возвращает true, потому что HashSet проверяет a.equals( b )
.