Будет ли метод Java (HashSet <String>) () проверять равенство строк или идентичность объекта? - PullRequest
46 голосов
/ 23 января 2012

Допустим, у меня есть этот код на 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"?Всегда ли мне это гарантировано? Если нет, то когда мне это не гарантировано?А что если я захочу сделать что-то похожее с объектами, кроме Strings?

Ответы [ 6 ]

52 голосов
/ 23 января 2012

Использует equals() для сравнения данных.Ниже из javadoc для Set

добавляет указанный элемент e к этому набору, если набор не содержит элемента e2, такого что (e == null? E2 == null:e.equals (e2)).

Метод equals() для String выполняет посимвольное сравнение.Из javadoc для String

Результат имеет значение true тогда и только тогда, когда аргумент не равен NULL и является объектом String, представляющим ту же последовательность символов, что и этот объект

6 голосов
/ 23 января 2012

На самом деле, HashSet не делает ни .

Его реализация использует HashMap, и вот соответствующий код, который определяет, установлен ли набор contains() (на самом деле он внутри метода getEntry () HashMap):

if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k))))

, который:

  • требует, чтобы хэши были равны, а
  • требует либо равенство объектов, либо equals() возвращает true

Ответ "да": wordSet.contains(b) всегда будет возвращаться true

3 голосов
/ 23 января 2012

Две вещи:

  1. Набор будет довольно бесполезным, если он не вызовет метод equals () для определения равенства.wordset.contains (b) вернет true, потому что a.equals (b) == true.

  2. Вы не можете быть полностью уверены, что a и b указывают на разные объекты.Проверьте String.intern () для более подробной информации.

3 голосов
/ 23 января 2012

На самом деле, и a, и b ссылаются на один и тот же объект, поскольку строковые литералы в Java автоматически интернируются.

1 голос
/ 23 января 2012

В конечном итоге contains будет проверять метод equals, а не проверку его идентификатора объекта для метода contains.Следовательно, для вызова contains будет вызван метод equals.Это структура вызова метода 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;
    }
0 голосов
/ 23 января 2012

Равенство.В вашем примере contains() возвращает true, потому что HashSet проверяет a.equals( b ).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...