В Java набор не может содержать два уникальных объекта, тогда как список не имеет этого ограничения. Каков механизм в наборе, который идентифицирует уникальные объекты. Скорее всего, это может быть реализация метода equals или метода hashCode, или обоих добавляемых объектов. Кто-нибудь знает, каков на самом деле механизм идентификации уникальных объектов. Это метод equals, метод hashcode или оба метода или что-то еще?
Уникальная идентификация объекта Java Set
Ответы:
Это зависит от реализации Set
. Для HashSet
и LinkedHashSet
используются методы equals
и hashCode
. Для TreeSet
используется естественный Comparator
объекта или специально предоставленный Comparator
.
По сути, это объясняется в Set
javadoc ( выделение мое):
Коллекция, не содержащая повторяющихся элементов. Говоря более формально, наборы не содержат пары элементов e1 и e2, таких что e1.equals(e2), и не более одного нулевого элемента. Как следует из названия, этот интерфейс моделирует математическую абстракцию множеств.
Интерфейс Set накладывает дополнительные условия, помимо унаследованных от интерфейса Collection, на контракты всех конструкторов и на контракты методов add, equals и hashCode.
TreeSet
имеет другое поведение, поскольку реализует SortedSet
(этот интерфейс расширяет интерфейс Set
). Из его javadoc (выделено мной):
Набор, который дополнительно обеспечивает общий порядок своих элементов. Элементы упорядочиваются с использованием их естественного порядка или с помощью компаратора, который обычно предоставляется во время создания отсортированного набора. Итератор набора будет проходить по набору в порядке возрастания элементов.)
Обратите внимание, что порядок, поддерживаемый отсортированным набором (независимо от того, предоставлен явный компаратор или нет), должен быть согласован с equals, если отсортированный набор должен правильно реализовать интерфейс Set (см. интерфейс Comparable или интерфейс Comparator для точного определения соответствия с equals.) Это так, потому что интерфейс Set определен в терминах операции equals, но отсортированный набор выполняет все сравнения элементов, используя свой метод compareTo (или сравнение).
Источник HashSet: кажется, что элементы хранятся как ключи в HashMap
(для чего требуются уникальные ключи), а метод put
в HashMap
проверяет следующее:
if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
Таким образом, он сравнивает оба хэша и запускает equals
.
TreeSet использует TreeMap для поддержки своих данных, а TreeMaps put
использует компаратор.