Почему объекты, добавляемые в TreeSet, должны иметь возможность сравнения?

«Почему объекты, добавляемые в TreeSet, должны иметь возможность сравнения?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

TreeSet в Java реализован как сбалансированное бинарное дерево поиска (красно-черное дерево). Для корректного размещения элементов в дереве и поддержания их в отсортированном порядке TreeSet должен уметь сравнивать любые два добавляемых объекта.

Существует два способа обеспечить сравнение:

  1. Естественный порядок (Natural Order): Класс элементов должен реализовывать интерфейс Comparable<T>.
  2. Внешний порядок (Custom Order): В конструктор TreeSet должен быть передан объект Comparator<T>.

Если не выполнить ни одно из этих условий, при попытке добавления элемента будет выброшено ClassCastException.

Пример с Comparable:

class Person implements Comparable<Person> {
    private String name;

    @Override
    public int compareTo(Person other) {
        return this.name.compareTo(other.name); // Сортировка по имени
    }
}

TreeSet<Person> set = new TreeSet<>(); // Используется natural order
set.add(new Person("Alice"));

Пример с Comparator:

TreeSet<Person> set = new TreeSet<>(
    Comparator.comparingInt(Person::getAge) // Сортировка по возрасту
);

Пример ошибки:

TreeSet<Object> set = new TreeSet<>();
set.add(new Object()); // ClassCastException: Object cannot be cast to Comparable

Это требование отличает TreeSet от HashSet, которому для работы нужны только hashCode() и equals().