The below is my code
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);
}
}
As I have defined my own comparator of type Number , but still when I'm adding any thing else that is a string to it, it's not giving me any exception. It's simply working fine. I'm getting the output as
[1, 1.4, 1, 1a]
Can any one please explain why it's happening.
The problem is a mixture of some poor practices:
TreeSet
NumberComparator
is generic (Number
is a type parameter)The fact that Number
is a type parameter here means that type erasure means you won't actually be casting to the real Number
type.
If you change your comparator to:
class NumberComparator implements Comparator<Number> {
public int compare(Number o1, Number o2) {
return 1;
}
}
and your calling code to:
TreeSet set = new TreeSet(new NumberComparator());
then I'd expect an exception.
Further, if you change your code to not use the raw type:
TreeSet<Number> set = new TreeSet<Number>(new NumberComparator());
then you'll get a compile-time error instead.
A Comparator
for a TreeSet
is used for ordering, not for throwing CCEs. Since your comparator is designed to return 1
for everything, it means that the ordering wouldn't be right.
That is the reason your output is not ordered.
Be sure to read the documentation of the constructor of 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));
}
It clearly states that if you try to add any other element other than the ones the Comparator
is designed for, it would throw a ClassCastException
. You could simulate this if you don't use generics by trying to add a String
. If you do use generics, however, this would be just a compile time issue.
Meanwhile, you should be using generics consistently.
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>());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With