我是一个有一点C++经验的Java新手,我正在尝试用Java语言创建一组集合,如下所示(类似于在C++中所做的事情):
Set< Set< String > > collection = new TreeSet< Set< String > >();
Set< String > entry = new TreeSet< String >();
collection.add( entry );这可以很好地构建,但是当程序执行时,会抛出一个java.util.TreeSet cannot be cast to java.lang.Comparable异常。
在不重新实现轮子的情况下,如何在Java中拥有一组集合?
另外,Java允许编译损坏的代码(例如,类型不匹配)的处理是什么?
提前感谢您的反馈。
发布于 2012-04-15 03:13:05
在TreeSet的合同中,要求所有条目必须为Comparable,否则您必须提供Comparator。(这也是为什么您没有看到编译时错误的原因:只有在没有显式Comparator的情况下才会将条目转换为Comparable。)
它与泛型无关,它来自于TreeSet本身的实现:因为它是一个二叉树,只有当条目能够以某种方式排序时,它才有意义。
如果您详细介绍了您的具体问题,我们可能会帮助您找到所需的确切数据结构,但通常情况下,如果您不关心集合中元素的顺序,则会使用HashSet。而且,通常情况下,Sets的Set通常是设计草率的标志。
发布于 2012-04-15 03:15:38
如果要将对象添加到TreeSet集合,则该对象的类型必须实现Comparable接口,而TreeSet本身并不实现该接口。或者,您可以通过使用不同的构造函数创建Comparator来提供TreeSet。
在这个特定场景中使用TreeSet并没有多大意义,因为根据定义,这是一个有序集合,您似乎不需要对元素进行排序。您可以尝试使用HashSet。
此外,为了回答你的第二个问题,这个错误只在运行时出现,因为你正在利用多态行为,即你正在添加一个Set,它实际上在运行时绑定到一个TreeSet。此信息在编译时是未知的。
发布于 2012-04-15 10:22:16
问题是,从泛型的角度来看,TreeSet并不是完全“类型安全”的,因为它需要能够接受自定义比较器或使用自然排序。
如果TreeSet仅使用自然排序,则可以将其声明为TreeSet<E extends Comparable<? super E>>,并且它将是类型安全的--不能简单地将自身不可比较的类型用作参数。另一方面,如果它总是使用比较器,那么它也是类型安全的。
但是它现在的设计方式允许您创建一个没有比较器的TreeSet (因此使用自然排序),其元素类型不能与其本身进行比较。没有编译时检查来强制执行这一点。只有在运行时才会注意到该故障。
实际上,有一种方法可以修复TreeSet。它可以同时支持自然排序和自定义比较器,并且是类型安全的:
对于自然排序情况,comparator
TreeSet。工厂方法可以具有泛型类型绑定<E extends Comparable<? super E>>,该绑定泛型要求类型与其自身可比较(我不知道为什么Java库设计者不这样做。
https://stackoverflow.com/questions/10156500
复制相似问题