TreeSet
有一个带比较器的构造函数,这意味着即使您存储的对象本身不是Comparable
个对象,也可以提供自定义比较器。
是否有类似的无序集实现? (例如HashSet<T>
的替代方法,它采用“hasher”对象计算equals()
和hashCode()
对象T可能与对象自己的实现不同?)
C ++ std::hash_set
给你这个,只是想知道是否有适合Java的东西。
编辑:@Max提出了关于equals()
的良好技术观点 - 足够公平;通过Map.containsKey()
TreeMap
和HashMap
键确实如此。但是否有其他众所周知的数据结构可以通过自定义哈希来组织?
答案 0 :(得分:9)
不,Collections
规范不支持“hasher”对象。您当然可以实现支持此功能的集合,但另一种方法是将Hasher
视为您在HashSet
中存储的包装对象。
Set<HasherWrapper<Foo>> set = new HashSet<HasherWrapper<Foo>>();
set.add(new HasherWrapper(foo));
...
然后包装类看起来像:
private class HasherWrapper<T> {
T wrappedObject;
public HasherWrapper(T wrappedObject) {
this.wrappedObject = wrappedObject;
}
@Override
public int hashCode() {
// special hash code calculations go here
}
@Override
public boolean equals(Object obj) {
// special equals code calculations go here
}
}
答案 1 :(得分:4)
标准库中没有这样的实现,但它不会阻止您自己滚动。这是我经常想要拥有的东西。
请参阅http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4771660,原因如下:
我们希望避免这种复杂性。我们认真地接受了这个想法 在收集框架设计时,但拒绝了它。该 功率重量比似乎很低。我们觉得平等就是你 想要95%的时间; ==,4%;和别的东西1%。写得明智 当等式谓词时,批量操作的合同非常棘手 不同。
答案 2 :(得分:1)
不,没有,也没有规范。而且,你误解了TreeSet
使用Comparator
的方式。
注意由一组维护的排序(无论是否显式 比较器提供)必须与equals一致,如果是的话 正确实现Set接口。 (参见可比较者或比较者 对于与equals一致的精确定义。)就是这样 因为Set接口是根据equals操作定义的, 但是TreeSet实例使用它执行所有元素比较 compareTo(或compare)方法,因此两个被认为相等的元素 从该集合的角度来看,通过这种方法是相等的。该 集合的行为即使其排序不一致也是明确定义的 与...平等它只是没有遵守集合的一般合同 接口
C类的自然排序据说是一致的 当且仅当e1.compareTo(e2)== 0具有相同的布尔值时才等于 作为类C的每个e1和e2的e1.equals(e2)。注意null不是 任何类的实例,e.compareTo(null)应抛出一个 即使e.equals(null)返回false,也会出现NullPointerException。
boolean contains(Object o)
如果此集合包含,则返回true 指定的元素。更正式地说,当且仅当这样时,返回true 集合包含至少一个元素e,使得(o == null? e == null:o.equals(e))。
因此,根据规范,不能有任何类实现Collection<E>
接口,完全依赖于某些外部Comparator样式对象来插入对象。所有集合都应使用equals
类的Object
方法来验证对象是否已插入。
答案 3 :(得分:0)
绝对没有类似的东西,hashcode()
和equals()
定义了对象的属性,不应该更改。它们定义了使对象彼此相等的原因,并且这不应该从一个集合到另一个集合。做你正在谈论的唯一方法是子类化对象并编写一个新的hashcode()
和equals()
,如果子类有一个应该添加的定义变量,那么这才有意义。除了超类“hashcode()
和equals()
之外。我知道这可能不是你的目标,但我希望这会有所帮助。如果你想要更多地解释你的理由,那么如果存在一个更好的解决方案可能会有所帮助。