Ответ
TreeSet добавит оба объекта, что нарушает контракт Set (уникальность элементов). TreeSet определяет уникальность исключительно через compareTo/Comparator, игнорируя equals().
Пример нарушения контракта:
class InconsistentItem implements Comparable<InconsistentItem> {
private int id;
private String name;
// equals сравнивает только id
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof InconsistentItem)) return false;
return this.id == ((InconsistentItem) o).id;
}
// compareTo сравнивает name
@Override
public int compareTo(InconsistentItem other) {
return this.name.compareTo(other.name);
}
// hashCode на основе id
@Override
public int hashCode() { return Objects.hash(id); }
}
TreeSet<InconsistentItem> set = new TreeSet<>();
InconsistentItem item1 = new InconsistentItem(1, "apple");
InconsistentItem item2 = new InconsistentItem(1, "banana"); // Тот же id!
set.add(item1);
set.add(item2); // Добавится, хотя equals() вернет true!
System.out.println(set.size()); // 2 - НАРУШЕНИЕ: в Set дубликаты!
System.out.println(item1.equals(item2)); // true
Правила TreeSet:
- Уникальность определяется
compareTo()(0 = дубликат) - Сортировка также через
compareTo() - equals() игнорируется для определения дубликатов
Best practice:
// compareTo и equals ДОЛЖНЫ быть согласованы
@Override
public int compareTo(MyItem other) {
int result = this.name.compareTo(other.name);
if (result == 0) {
result = Integer.compare(this.id, other.id);
}
return result;
}
@Override
public boolean equals(Object o) {
// Такая же логика, как в compareTo
if (!(o instanceof MyItem)) return false;
MyItem other = (MyItem) o;
return Objects.equals(this.name, other.name)
&& this.id == other.id;
}
Вывод: Всегда обеспечивайте согласованность между compareTo() и equals()!