Почему я не получаю исключение класса или что-то еще при добавлении элемента в 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;
}
}