When I try to run the below code I get a runtime error: java.lang.Integer cannot be cast to java.lang.String
Set vals = new TreeSet();
vals.add(1);
vals.add("two");
System.out.println(vals);
I tried to replace it with HashSet, HashLinkedSet, ArrayList and so on, and they all ran and printed the answer. It looks like only TreeSet fails to work!
My assumption is that this happens because a TreeSet does a comparison between the objects at runtime, which would it fail.
However, I also know that other kinds of sets (like a HashSet, for example) needs to do the same comparison (but maybe in a HashSet the comparison occurs between two hashed values? And there is no casting that fails?)
Why is this happening?
TreeSet stores values in sorted order, hence, it needs to compare two elements for order, not just equality. It internally uses a TreeMap to store the values, and while inserting values in the TreeMap, the map compares keys for odering. The error occurs during comparison as evident from stack trace
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at java.lang.String.compareTo(Unknown Source)
at java.util.TreeMap.put(Unknown Source)
at java.util.TreeSet.add(Unknown Source)
at Test.main(Test.java:10)
The signature of compareTo
method of String class looks like below:
public int compareTo(String anotherString)
So, when a call is made to this method with int
argument as in your code the set contains an int
value, the runtime error occurs with respect to Class cast
Similary, if you had added String first into set and then added Integer, as shown below:
Set vals = new TreeSet();
vals.add("two");
vals.add(1);
System.out.println(vals);
You would have seen exception from Integer class
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at java.lang.Integer.compareTo(Unknown Source)
at java.util.TreeMap.put(Unknown Source)
at java.util.TreeSet.add(Unknown Source)
at Test.main(Test.java:10)
In case of HashSet, this issue does not occur because elements are being compared for equality.
The signature of equals
method of String class looks like:
public boolean equals(Object anObject)
Here, as you can see, the input parameter is java.lang.Object, and an integer can be passed to this function without any errors. The implementation internally uses instanceof
operator to check for type compatiblity, and avoids ClassCastException
You can say that it is difference between how compareTo
and equals
are implemented is resulting in this error.