尝试打印原始类型集的内容时Java的TreeSet行为

时间:2015-07-12 17:17:16

标签: java casting treeset raw-types

当我尝试运行以下代码时,我收到运行时错误: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中,比较发生在两个散列值之间?并且没有失败的转换?)

为什么会这样?

1 个答案:

答案 0 :(得分:0)

TreeSet 以排序顺序存储值,因此,它需要比较两个元素的顺序,而不仅仅是相等。它在内部使用 TreeMap 来存储值,并在TreeMap中插入值时,映射会比较用于odering的键。从堆栈跟踪中可以看出错误发生在比较过程中

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类的compareTo方法的签名如下所示:

 public int compareTo(String anotherString)

因此,当在代码中使用int参数调用此方法时,该集合包含int值,运行时错误发生在类强制转换

同样,如果您先将String添加到set中,然后添加Integer,如下所示:

    Set vals = new TreeSet();
    vals.add("two");
    vals.add(1);
    System.out.println(vals); 

你会看到Integer类的异常

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类的equals方法的签名如下:

public boolean equals(Object anObject)

在这里,正如您所看到的,输入参数是java.lang.Object,并且可以将整数传递给此函数而不会出现任何错误。该实现在内部使用instanceof运算符来检查类型兼容性,并避免ClassCastException

您可以说compareToequals的实施方式之间存在差异导致此错误。