Возможно ли, что TreeSet equals HashSet, но не наоборот HashSet equals TreeSet?
Вопрос на собеседовании, который сильно меня озадачил: возможно ли, что TreeSet equals HashSet, но не наоборот HashSet equals TreeSet? Я ответил "нет", но это был неправильный ответ. Правильный ответ: "да".
Как такое вообще возможно?
Свободный перевод вопроса: «Is it possible that TreeSet equals HashSet but not HashSet equals TreeSet».
Ответы (2 шт):
ДА, в некоторых случаях такое возможно: TreeSet может быть равен HashSet, но не наоборот. Пример:
TreeSet<String> treeSet = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
HashSet<String> hashSet = new HashSet<>();
treeSet.addAll(List.of("A", "b"));
hashSet.addAll(List.of("A", "B"));
System.out.println(hashSet.equals(treeSet)); // false
System.out.println(treeSet.equals(hashSet)); // true
Причина в том, что TreeSet использует Comparator для сравнения объектов, а HashSet использует hashCode.
При формировании ответа использовался ответ на вопрос «Is it possible that TreeSet equals HashSet but not HashSet equals TreeSet» от участника @aniket-sahrawat.
НЕТ, такое невозможно без нарушения основного контракта equals класса Object, одним из условий которого является симметричность, т. е. x.equals(y) тогда и только тогда, когда y.equals(x).
НО, классы TreeSet и HashSet по-разному реализуют контракт equals интерфейса Set, который требует среди прочего, чтобы каждый элемент передаваемого набора содержался в текущем наборе. Для определения вхождения элемента в набор вызывается метод contains, который для класса TreeSet использует Comparator, а для класса HashSet использует hashCode.
В итоге:
ДА, в некоторых случаях такое возможно.