在Java中,Comparator接口允许客户端为任何类型指定equals()和compare()方法。可以将比较器传递给需要排序的大多数(或可能是所有)集合,并且将使用Comparator中的方法而不是指定类的方法。这允许客户端以与自然顺序不同的方式对对象进行排序,甚至可以对没有自然排序的对象进行排序(即不实现Comparable)。
为什么没有类似的哈希接口?它可以指定两个方法,hashCode()和equals(),并且对于HashSets或HashMaps非常有用,就像Comparators用于排序一样。
编辑:对于那些将此问题标记为this other question的副本的人,我会提到另一个问题,问为什么hashCode包含在每个类而不是接口中,而这个问题是关于将散列函数抽象为允许多次实现它。
答案编辑:获得此功能的最佳方法似乎是:
- 如果你没有使用外部库和/或已经在使用Guava(由于很多原因这是一个很棒的库),Guava有一个允许这个的Equivalence类。
- 如果您不想使用外部库,可以使用自定义构建的适配器,类似于this SO question上的最佳答案所做的。
答案 0 :(得分:4)
表格的问题
“为什么Java没有XXX”
除了使用通用
之外,很难客观地回答“我们不知道,因为做出决定时,没有人在场。”
在这种情况下:
从表面上看,这项要求可以从技术角度实施。
此要求已通过RFE多次提出。最直接的是http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6435963。 RFE被标记为WONT FIX,但没有给出特别的理由。
第三方图书馆可以满足此要求。
我的阅读这是因为它不受支持,因为它对于足够的人来说并不足够重要,因为它需要得到支持。我会说他们对此做了一个合理的调用。
答案 1 :(得分:1)
我也认为这样的界面会很方便,特别是作为一种考虑集合中不同类型的平等的方法。它应该与您创建对象Comparable
的方式类似,但仍然通过提供其他Comparator
来覆盖特定集合中的行为。
正如在this question中指出的那样,Guava有一个Equivalence
类提供了一种方法来实现这一点,通过包装你的类并让你在包装器级别定义“相等”在这里意味着什么上下文。
如果你的问题确实是为什么在语言设计时没有发生这种情况......嘿,嘿,James Gosling和公司只是人类,对吗?
答案 2 :(得分:0)
Hashing实际上只有一个要求:就像哈希方法一样。因此,您可以在不知道谁将以何种方式和目的使用它的情况下为类型实现它。所以对象本身的哈希方法就足够了。
另一方面,等于在不同背景下具有不同的含义。例如,您可以按名字,姓氏,年龄,大小,体重,俱乐部会员资格的时间对人进行排序......因此,对于单个班级,有不同的等同(和'小于')实现是有意义的。
当然没有什么能阻止你创建这样的界面并使用它......
答案 3 :(得分:0)
您可以随时更改hashcode()以说明HashMap如何在Map中排列您的对象,并通过在您的类中实现有效的哈希码方法来提高其性能。
HashMap如何从散列数据中执行添加和删除是HashMap内部的,更改它基本上意味着更改添加,删除方法等。
此外,排序是一种常用功能,经常使用,对于极少数情况,如果您真的想要更改地图中的散列方式,则始终可以选择扩展地图。
答案 4 :(得分:0)
让我试着说出我是怎么看的,为什么。
简单地说 - 您经常需要排序列表对象,但很少(如果有的话)需要交叉比较列表的标识 对象。
在Object中,方法 hashCode 是一种有用的辅助方法,其主要目的是提供 equals 方法。协议是,如果两个对象 hashCode 返回不同的值,等于不得返回true。
因此,方法 hashCode 和等于用于建立对象的标识。
方法 compareTo (在Comparable和Comparator中)提供另一个通用目的。它定义对象顺序,而不是标识。
简历 - compareTo 定义对象如何有序, hashCode (以及等于< / strong>)定义对象标识。
再次 - 练习贡献是你经常需要对一组对象进行排序,但你很少(如果有的话)必须采取一组对象并进行交叉比较他们的身份。