Почему мы приводим в Comparable в TreeMap - PullRequest
0 голосов
/ 01 марта 2020

Я изучаю Collections в Java, и наткнулся на приведенный ниже код в TreeMap API,

 if (key == null)
                throw new NullPointerException();
            Comparable<? super K> k = (Comparable<? super K>) key;
            do {
                parent = t;
                cmp = k.compareTo(t.key);
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    return t.setValue(value);
            } while (t != null);

Почему нам нужно привести к Comparable в первую очередь ? Поскольку key уже реализует Comparable и имеет переопределение compare(). Почему мы не можем позвонить key.compare(t.key)?

Ключ реализует Comparable.

Ответы [ 2 ]

2 голосов
/ 01 марта 2020

Документация TreeMap содержит следующую информацию:

Реализация {@link NavigableMap} на основе красно-черного дерева. Карта сортируется в соответствии с {@linkplain Comparable естественным порядком} ее ключей или {@link Comparator}, предоставляемым во время создания карты, в зависимости от того, какой конструктор используется.

два конструктора TreeMap (их больше, но применяется одно и то же правило) также применяются к этому указанному правилу c. Первый предполагает, что ключ обычно Comparable (и каждый вставленный ключ должен это делать), а второй предоставляет возможность предоставить пользовательский Comparator.

public TreeMap() {
    comparator = null;
}

public TreeMap(Comparator<? super K> comparator) {
    this.comparator = comparator;
}

Определение, какое поведение Если используется, реализация часто проверяется, если Comparator был инициализирован.

final int compare(Object k1, Object k2) {
    return comparator == null ? ((Comparable<? super K>)k1).compareTo((K)k2)
        : comparator.compare((K)k1, (K)k2);
}

Таким образом, ваше следующее предположение неприменимо:

Поскольку ключ уже реализует Comparable и с переопределением compare ().

Ключ K из Map может быть любого типа и не ограничивается Comparable. Это обеспечивает большую гибкость, поскольку иногда вы не можете сделать класс взаимно сопоставимым (например, если он поступает из сторонней библиотеки), или класс логически не имеет естественного порядка. Я бы рекомендовал прочитать документацию как Comparable и Comparator.

0 голосов
/ 01 марта 2020

key не объявлен как реализующий Comparable.

public V put(K key, V value) {

Он не может быть объявлен как сопоставимый в put(), поскольку в TreeMap можно поместить ключи, которые не реализуют Comparable - Вы должны предоставить компаратор тогда. Это показано чуть выше кода, который вы цитировали.

        // split comparator and comparable paths
        Comparator<? super K> cpr = comparator;
        if (cpr != null) {
            do {
                parent = t;
                cmp = cpr.compare(key, t.key);
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    return t.setValue(value);
            } while (t != null);
        }
        else {
            if (key == null)
                throw new NullPointerException();
            @SuppressWarnings("unchecked")
                Comparable<? super K> k = (Comparable<? super K>) key;
            do {
                parent = t;
                cmp = k.compareTo(t.key);
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    return t.setValue(value);
            } while (t != null);
        }

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...