Почему я не получаю исключение класса или что-то еще при добавлении элемента в TreeSet

Ниже мой код

class NumberComparator<Number> implements Comparator<Number> {
    public int compare(Number o1, Number o2) {
        return 1;
    }
}

public class Ex28 {
    public static void main(String[] args) {
        TreeSet set = new TreeSet(new NumberComparator<Number>());
        set.add(1);
        set.add(1.4f);
        set.add(1L);
        set.add("1a");
        System.out.println(set);
    }
}

Как я определил свой собственный компаратор типа Number, но все же, когда я добавляю что-то еще, что является строкой для него, это не дает мне никаких исключений. Это просто отлично работает. Я получаю вывод как

[1, 1.4, 1, 1a]

Может кто-нибудь объяснить, почему это происходит.

Ответ 1

Проблема представляет собой смесь некоторых плохих практик:

  • Используется необработанный тип для TreeSet
  • Ваш NumberComparator является общим (Number является параметром типа)

Тот факт, что Number является параметром типа, означает, что стирание типа означает, что вы фактически не будете отличать реальный тип Number.

Если вы измените свой компаратор на:

class NumberComparator implements Comparator<Number> {
    public int compare(Number o1, Number o2) {
        return 1;
    }
}

и ваш код вызова:

TreeSet set = new TreeSet(new NumberComparator());

тогда я ожидаю исключение.

Кроме того, если вы измените свой код, чтобы не использовать необработанный тип:

TreeSet<Number> set = new TreeSet<Number>(new NumberComparator());

тогда вы получите ошибку времени компиляции.

Ответ 2

A Comparator для a TreeSet используется для упорядочения, а не для выброса CCE. Поскольку ваш компаратор предназначен для возврата 1 для всего, это означает, что порядок не будет правильным.

Вот почему ваш вывод не упорядочен.

Обязательно прочитайте документацию конструктора TreeSet.

/**
 * Constructs a new, empty tree set, sorted according to the specified
 * comparator.  All elements inserted into the set must be <i>mutually
 * comparable</i> by the specified comparator: {@code comparator.compare(e1,
 * e2)} must not throw a {@code ClassCastException} for any elements
 * {@code e1} and {@code e2} in the set.  If the user attempts to add
 * an element to the set that violates this constraint, the
 * {@code add} call will throw a {@code ClassCastException}.
 *
 * @param comparator the comparator that will be used to order this set.
 *        If {@code null}, the {@linkplain Comparable natural
 *        ordering} of the elements will be used.
 */
public TreeSet(Comparator<? super E> comparator) {
    this(new TreeMap<>(comparator));
}

В нем четко указано, что если вы попытаетесь добавить какой-либо другой элемент, отличный от тех, для которых предназначен Comparator, он выбрал бы ClassCastException. Вы можете имитировать этот , если вы не используете generics, пытаясь добавить String. Однако, если вы используете дженерики, это будет просто проблемой времени компиляции.

Между тем, вы должны последовательно использовать дженерики.

class NumberComparator<C> implements Comparator<C> {
    public int compare(C o1, C o2) {
        return 1; // change this logic
    }
}

Set<Number> set = new TreeSet<>(new NumberComparator<Number>());

Ответ 3

Все сказали, что вы получите исключение класса, если вы определяете свой компаратор следующим образом:)

import java.util.Comparator;

class NumberComparator<Number> implements Comparator<java.lang.Number> {
public int compare(java.lang.Number o1, java.lang.Number o2) {


    return 1;
}
}