Java 尝试打印原始类型集的内容时的 TreeSet 行为
Java's TreeSet behavior when trying to println the content of a raw type set
当我尝试 运行 下面的代码时,出现 运行 时间错误:java.lang.Integer cannot be cast to java.lang.String
Set vals = new TreeSet();
vals.add(1);
vals.add("two");
System.out.println(vals);
我尝试用HashSet、HashLinkedSet、ArrayList等替换,都运行打印了答案。看来只有TreeSet不行了!
我的假设是,发生这种情况是因为 TreeSet 在 运行 时间对对象进行了比较,这会失败。
但是,我也知道其他类型的集合(例如 HashSet)需要进行相同的比较(但也许在 HashSet 中,比较发生在两个散列值之间?并且没有转换失败?)
为什么会这样?
TreeSet 以排序顺序存储值,因此,它需要比较两个元素的顺序,而不仅仅是相等性。它在内部使用 TreeMap 来存储值,并且在将值插入 TreeMap 时,地图会比较键以进行排序。从堆栈跟踪
可以明显看出,在比较期间发生错误
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)
String class 的 compareTo
方法的签名如下所示:
public int compareTo(String anotherString)
因此,当在您的代码中使用 int
参数调用此方法时,该集合包含一个 int
值,运行时错误发生在 Class 转换
同理,如果先把String加入set,再加入Integer,如下图:
Set vals = new TreeSet();
vals.add("two");
vals.add(1);
System.out.println(vals);
您会看到 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)
在 HashSet 的情况下,不会发生此问题,因为正在比较元素是否相等。
String class 的 equals
方法的签名如下所示:
public boolean equals(Object anObject)
这里可以看到,入参是java.lang.Object,给这个函数传一个整数就可以了,没有任何错误。该实现在内部使用 instanceof
运算符来检查类型兼容性,并避免使用 ClassCastException
你可以说是 compareTo
和 equals
的实现方式不同导致了这个错误。
当我尝试 运行 下面的代码时,出现 运行 时间错误:java.lang.Integer cannot be cast to java.lang.String
Set vals = new TreeSet();
vals.add(1);
vals.add("two");
System.out.println(vals);
我尝试用HashSet、HashLinkedSet、ArrayList等替换,都运行打印了答案。看来只有TreeSet不行了!
我的假设是,发生这种情况是因为 TreeSet 在 运行 时间对对象进行了比较,这会失败。
但是,我也知道其他类型的集合(例如 HashSet)需要进行相同的比较(但也许在 HashSet 中,比较发生在两个散列值之间?并且没有转换失败?)
为什么会这样?
TreeSet 以排序顺序存储值,因此,它需要比较两个元素的顺序,而不仅仅是相等性。它在内部使用 TreeMap 来存储值,并且在将值插入 TreeMap 时,地图会比较键以进行排序。从堆栈跟踪
可以明显看出,在比较期间发生错误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)
String class 的 compareTo
方法的签名如下所示:
public int compareTo(String anotherString)
因此,当在您的代码中使用 int
参数调用此方法时,该集合包含一个 int
值,运行时错误发生在 Class 转换
同理,如果先把String加入set,再加入Integer,如下图:
Set vals = new TreeSet();
vals.add("two");
vals.add(1);
System.out.println(vals);
您会看到 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)
在 HashSet 的情况下,不会发生此问题,因为正在比较元素是否相等。
String class 的 equals
方法的签名如下所示:
public boolean equals(Object anObject)
这里可以看到,入参是java.lang.Object,给这个函数传一个整数就可以了,没有任何错误。该实现在内部使用 instanceof
运算符来检查类型兼容性,并避免使用 ClassCastException
你可以说是 compareTo
和 equals
的实现方式不同导致了这个错误。