2013-11-26 3 views
5

Почему документация API Oracle Java для метода add() для TreeSet и HashSet состояния, что:Условные обозначения, используемые в Java документации

элемент е добавляется только если нет е2 в множестве, где (e==null ? e2==null : e.equals(e2))

Однако TreeSet использует compareTo(), в то время как HashSet использует hashCode() для определения равенства. Оба игнорируют значение equals(). Я обеспокоен тем, что документация неточна, или это мое понимание соглашения или алгоритма, который неисправен?

ответ

2

Вы считаете правильным, что документация TreeSet неверна.

Вы ввели неправильный адрес HashSet, так как он делаетequals(). hashCode() is не используется для проверки равенства, только для быстрого поиска.

+0

Если hashCode() установлен всегда для возврата того же кода, то поведение add(), как представляется, зависит от equals(). Но если я создаю объект, где equals() всегда возвращает «true» и не переопределяет hashCode() - поэтому он отличается для разных объектов, то add() добавит несколько объектов. Поэтому поведение add() кажется более сложным, чем указано в документах. Как говорит Луис, эти ситуации находятся вне контракта, но меня интересовала реализация (поскольку она не делала то, что она говорила) - кто-нибудь знает, есть ли каноническая спецификация? – user3038094

+0

@ user3038094 - я бы рекомендовал прочитать о том, как работает HashMap. то вы поймете, почему метод 'equals()' не всегда называется. независимо от того, в общем смысле, HashSet _does_ использует 'equals()' для тестирования равенства. – jtahlborn

+0

Спасибо jtahlborn - Я последовал твоему совету и посмотрю, что ты имеешь в виду. Если hashCode() отличается, то алгоритм не утруждает оценке equals(), он использует equals(), если hashCode() - то же самое. Предположительно это связано с тем, что hashCode() считается более быстрым для вычисления, чем equals(), или это связано с тем, что hashCode() нужно будет оценить? Так что было бы лучше сказать в документах: e == null? e2 == null: e.hashCode() == e2.hashCode()? e.hashCode() == e2.hashCode(): e.equals (e2) == 0 – user3038094

1

TreeSet объясняет это в доке:

Обратите внимание, что порядок поддерживается с помощью набора (предоставляются ли или нет явного сравнение) должен быть совместим с равными, если это правильно реализовать интерфейс Set. (См. Comparable или Comparator для точного определения соответствия с равными.) Это происходит потому, что интерфейс Set определен в терминах операции equals, но экземпляр TreeSet выполняет все сравнения элементов с помощью метода compareTo (или сравнения), поэтому два элементы, которые по этому методу считаются равными, равны, с точки зрения множества. Поведение множества хорошо определено, даже если его упорядочение не соответствует равным; он просто не подчиняется генеральному контракту интерфейса Set.

Для HashSet, это неявное ожидание документа о том, что объекты в Set правильно реализованы; если hashCode() неправильно реализован, то это не HashSet, нарушающее его спецификацию, но передаваемые ему объекты.

+0

«Поведение множества хорошо определено, даже если его упорядочение не соответствует равным». Однако поведение не так определено в документации, вот о чем мне было интересно. Почему именно документация не указана (точна) на этом? Лучше сказать: e == null? e2 == null: e.compareTo (e2) == 0) – user3038094

Смежные вопросы