为什么TreeSet.contains()不起作用?

时间:2010-08-17 11:41:27

标签: java classcastexception treeset

public class Empty {

    public static void main( String[] args ) {

        TreeSet<Class> classes = new TreeSet<Class>();
        classes.add( String.class );

        String test = new String();

        try{ 
            if( classes.contains(test.getClass()) ){
                System.out.println( "contains" );
            }
        }catch(ClassCastException cce){

            System.out.println( "Expected:  "  + classes );
            System.out.println( "But it was: " + test.getClass() );
        }
    }
}

为什么抛出ClassCastException

4 个答案:

答案 0 :(得分:8)

在没有显式比较器的情况下实例化TreeSet时,它期望插入的元素实现Comparable,但Class不实现此接口。

要修复,请为Class创建一个比较器:

Comparator<Class> classComp = new Comparator<Class>()
{
    @Override
    public int compare(Class o1, Class o2)
    {
        return o1.getName().compareTo(o2.getName());
    }
};
TreeSet<Class> classes = new TreeSet<Class>(classComp);

答案 1 :(得分:3)

TreeSet是一个有序集,因此您插入的任何元素都必须实现Comparable(除非您指定自定义Comparator)。 Class没有。

如果您不需要订购,则可以始终使用无序集,例如HashSet。否则,您需要提出自己的订购。

来自Javadoc(强调我的):

  

基于的NavigableSet实现   一个TreeMap。 元素已订购   使用他们的自然顺序,或通过   比较器在创建时提供   时间,具体取决于构造函数   使用。

     

此实现提供   保证log(n)的时间成本   基本操作(添加,删除和   包含)。

     

请注意由a维护的排序   设置(无论是否明确   提供比较器)必须   如果是,则与等于一致   正确实现Set接口。   (参见Comparable或Comparator for a   精确定义符合   等于。)这是因为Set   接口是根据的定义的   等于操作,但是一个TreeSet   instance执行所有元素   比较使用compareTo(或   比较)方法,所以两个元素   被这种方法认为是平等的,   从集合的角度来看,是平等的。   集合的行为是明确定义的   即使它的排序不一致   与...平等它只是没有服从   Set接口的一般合约。

另请参阅:Comparator

答案 2 :(得分:1)

  

块引用   为什么抛出ClassCastException?

这是由TreeMap的实现引起的,TreeSet是TreeMap的一个关键集基于它。

java.lang.Class没有实现java.lang.Comparable接口,因此它将抛出ClassCastException的异常。

答案 3 :(得分:0)

实际错误为java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.Comparable 。这是 - TreeSet对元素强制排序。如果您使用HashSet,一切正常。