Object
具有hashCode
方法,但它仅在HashSet
或HashMap
等关联容器中使用。它为什么这样设计?具有Hashable
方法的hashCode
接口看起来更加优雅。
答案 0 :(得分:7)
在我看来,主要论点是,可以为任何Java对象计算明确定义的默认hashCode
,以及同样明确定义的equals
。没有充分的理由拒绝所有对象的这个功能,当然有很多理由不来隐瞒它。所以这在我的书中是明白的。
答案 1 :(得分:0)
这个问题声称是另一个问题的副本,它询问为什么没有任何界面的行为类似于Comparator
(与Comparable
不同),而是用于散列。 .NET包含这样一个名为IEqualityComparer
的接口,它看起来也像Java一样。事实上,如果有人想要,例如有一个Java集合,例如以不区分大小写的方式将字符串映射到其他对象(可能是IEqualityComparer
的最常见用法)必须将字符串包装在hashCode
和equals
方法不区分大小写的对象中
我怀疑最大的问题是,当一个" equalityComparer"界面可能很方便,在许多情况下,有效地测试等价关系需要缓存信息。例如,虽然不区分大小写的字符串散列函数可以创建传入字符串的仅大写的副本并在其上调用hashCode
,但是很难避免每次请求特定的散列码string重复转换为大写和该大写值的散列。相比之下,一个"不区分大小写的字符串"对象可以包含字符串的仅大写副本的字段,然后只需为该实例生成一次。
EqualityComparer
可以实现合理的性能,如果它包含类似WeakHashMap<string,string>
的内容,将原始字符串转换为仅大写字符串,但这样的设计要么需要不同的线程才能使用不同的EqualityComparer
尽管缺少外部可见状态,但实际上还需要性能抢夺锁定和同步代码,即使在单线程场景中也是如此。
顺便提一下,比较器式接口产生的第二个问题是使用外部提供的比较器(无论是等级还是相等)的集合类型是比较器本身成为类的状态的一部分。使用它。如果哈希表使用不同的EqualityComparer实例,则可能无法知道它们可以被安全地视为等效,即使两个比较器在所有情况下的行为都相同。