我正在尝试创建一个使用二叉搜索树实现各种功能的混合列表。该类试图实现 List< E >
.为了索引,这些树使用比较来决定数据应该放在父节点的左 child 还是右 child 中。这是使用 Comparator
完成的构造函数设置的变量:
private Comparator<E> comparator; // method for ordering the tree
这确保类型 E
将在某种程度上具有可比性。然而,问题在于列表接口(interface)如何声明其抽象函数。例如:
public boolean contains(Object o);
通常,我会假设参数是可比较的,然后在树上使用递归查找方法,但因为参数是 Object,所以我无法做出这种假设。
我已尝试确保它的类型为 E
通过执行以下操作:
if (o instanceof E) {}
但它不起作用并给了我这个建议:
Cannot perform instanceof check against type parameter E.
Use its erasure Object instead since further generic type information will be erased at runtime
关于如何解决这个问题有什么想法吗?
编辑:
类是这样被实例化的:
TreeCollection<Integer> c = new TreeCollection<>(
new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
});
最佳答案
对于您的情况,没有完美的答案。 Comparator
和 .contains()
方法之间存在某种冲突,前者的正确使用由编译时泛型强制执行,后者的约定取决于 。 equals()
,它接受任何类型的对象(没有编译时约束),其逻辑必须基于运行时信息。 TreeSet
也面临这个问题。
你的数据结构的重点是查找是 O(log n),所以你不能遍历每个元素并检查;相反,您必须通过使用比较器将给定值与元素进行比较来向下搜索二叉搜索树。但是由于给定的元素是任何类型的对象,我们不知道比较器可以接受它。我认为最好的解决方案就是将其转换为 E
并假设您的比较器可以接受它。如果对象不是 E
的实例,比较器可能会以某种方式抛出 ClassCastException
,您可以让该异常传递给用户。 TreeSet
采用这种方法——TreeSet.contains()
的文档说当无法将指定对象与元素进行比较时,它会抛出 ClassCastException
在集合中。
虽然这使得 .contains()
不那么通用,但它避免了破坏 Collection.contains()
的约定,因为在有人给我们一个对象的情况下.contains()
我们的比较器无法比较,根据契约(Contract),正确答案可能是真或假,但我们无法有效地确定;因此,我们不会返回可能出错的内容,而是抛出一个异常,这是合约中允许的。
关于java - 实现java接口(interface)时保证 "Object o"参数是同一个泛型类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25090447/