![](/img/trans.png)
[英]Why can we supply a Comparator to TreeSet but not something like Hasher to HashSet?
[英]TreeSet/TreeMap equivalent for HashSet/HashMap (custom hasher)
TreeSet
有一个带比较器的构造函数,这意味着即使您存储的对象本身不是Comparable
对象,您也可以提供自定义比较器。
是否有类似的无序集实现? (例如, HashSet<T>
的替代方法是采用“hasher”对象来计算对象T的equals()
和hashCode()
,这些对象可能与对象自己的实现不同?)
C ++ std::hash_set
为您提供了这个,只是想知道是否有适合Java的东西。
编辑:@Max提出了一个关于equals()
的良好技术观点 - 足够公平; 通过Map.containsKey()
对TreeMap
和HashMap
键Map.containsKey()
。 但是否有其他众所周知的数据结构可以通过自定义哈希来组织?
不, 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
}
}
标准库中没有这样的实现,但它不会阻止您自己滚动。 这是我经常想要拥有的东西。
请参阅http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4771660 ,原因如下:
我们想避免复杂性。 在收集框架设计时,我们认真地接受了这个概念,但拒绝了它。 功率重量比似乎很低。 我们觉得平等是你想要的95%的时间; ==,4%; 和别的东西1%。 当等式谓词不同时,为批量操作编写合理的合同是非常棘手的。
不,没有,也没有规范。 而且,你误解了TreeSet
使用它的Comparator
。
来自TreeSet Javadoc :
请注意,如果要正确实现Set接口,则由set维护的排序(无论是否提供显式比较器)必须与equals一致。 (有关与equals一致的精确定义,请参阅Comparable或Comparator。)这是因为Set接口是根据equals操作定义的,但TreeSet实例使用compareTo(或compare)方法执行所有元素比较,因此从集合的角度来看,通过这种方法被认为相等的元素是相等的。 集合的行为即使其排序与equals不一致也是明确定义的; 它只是不遵守Set接口的一般合同。
当且仅当e1.compareTo(e2)== 0与c1的每个e1和e2的e1.equals(e2)具有相同的布尔值时,C类的自然排序被认为与equals一致。 null不是任何类的实例,并且即使e.equals(null)返回false,e.compareTo(null)也应抛出NullPointerException。
来自收藏夹javadoc :
boolean contains(Object o)
如果此collection包含指定的元素,则返回true。 更正式地,当且仅当此集合包含至少一个元素e时才返回true(o == null?e == null:o.equals(e))。
因此,通过规范,不能有任何类实现Collection<E>
接口并且完全依赖于某些外部Comparator样式的对象来插入对象。 所有集合应使用Object
类的equals
方法来验证对象是否已插入。
绝对没有类似的东西, hashcode()
和equals()
定义了对象的属性,不应该更改。 它们定义了使对象彼此相等的原因,并且这不应该从一个集合到另一个集合。 做你正在谈论的唯一方法是子类化对象并编写一个新的hashcode()
和equals()
,如果子类有一个应该添加的定义变量,这只会有意义。超类' hashcode()
和equals()
。 我知道这可能不是你的目标,但我希望这会有所帮助。 如果你想要更多地解释你的推理,那么如果存在一个更好的解决方案可能会有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.