2

在 Java 中,Comparator 接口允许客户端为任何类型指定 equals() 和 compare() 方法。Comparator 可以传递给大多数(或者可能是所有)需要排序的集合,并且将使用 Comparator 中的方法而不是指定类的方法。这允许客户端以不同于其自然顺序的方式对对象进行排序,甚至可以对没有自然顺序的对象进行排序(即不实现 Comparable)。

为什么没有类似的哈希接口?它可以指定两种方法,hashCode() 和 equals(),并且对 HashSets 或 HashMaps 很有用,就像比较器对排序很有用一样。

编辑:对于那些将这个问题标记为另一个问题的副本的人,我会提到另一个问题询问为什么 hashCode 包含在每个类中而不是接口中,而这个问题是关于抽象散列函数以允许它的多个实现.

答案编辑:获得此功能的最佳方法似乎是:

- 如果您可以使用外部库和/或已经在使用 Guava(由于很多原因,这是一个很棒的库),Guava 有一个Equivalence类允许这样做。

- 如果您不想使用外部库,则可以使用自定义构建的适配器,类似于此 SO question的最佳答案中所做的。

4

5 回答 5

4

表格问题

“为什么 Java 没有 XXX”

很难客观地回答,除非有一个通用的

“我们不知道,因为做出决定时房间里没有人。”

在这种情况下:

  • 从表面上看,这个要求是可以实现的……从技术角度来看。

  • 该要求已通过 RFE 多次提出。最直接的一个是 http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6435963。RFE 被标记为 WONT FIX,但没有给出具体原因。

  • 3rd 方库可以并且已经充分满足了此要求。

我对此的解读是,它不被支持,因为对于足够多的人来说,它被认为不够重要以至于需要支持。我会说他们对此做出了合理的决定。

于 2013-03-16T23:54:52.457 回答
1

我也认为这样的界面会很方便,特别是作为一种考虑集合中不同类型的平等的方式。它应该类似于您可以创建一个对象的方式Comparable,但仍然通过提供其他一些来覆盖特定集合中的该行为Comparator

正如在这个问题中指出的那样,Guava 有一个Equivalence类提供了一种方法来做到这一点,通过包装你的类并让你在包装级别定义在这种情况下“平等”的含义。

如果您的问题真的是为什么在语言设计时没有发生这种情况……好吧,嘿,James Gosling和公司只是人类,对吗?

于 2013-03-16T23:09:57.217 回答
0

散列实际上只有一个要求:像散列方法一样。因此,您可以为一种类型实现它,而无需知道谁会以何种方式以及出于何种目的使用它。所以对象本身的hash方法就足够了。

另一方面,Equals 在不同的上下文中具有不同的含义。例如,您可以按名字、姓氏、年龄、大小、体重、加入俱乐部的时间对人员进行排序……因此,对单个班级有不同的相等(和“小于”)实现是有意义的。

当然,没有什么能阻止您创建这样的界面并使用它......

于 2013-03-16T23:00:50.177 回答
0

您可以随时更改 hashcode() 以说明 HashMap 如何在 Map 中排列您的对象,并通过在您的类中实现有效的 hashcode 方法来提高其性能。

HashMap 如何从散列数据中执行添加和删除是 HashMap 内部的,更改它基本上意味着更改添加、删除方法等。

此外,排序是一个更常用的常见功能,并且在极少数情况下,当您真的想更改地图中散列的发生方式时,始终可以选择扩展地图。

于 2013-03-16T23:05:42.307 回答
0

让我试着说说我是怎么看的,为什么。

简而言之 - 您经常需要对列表objects进行排序,但很少(如果有的话)需要交叉比较object列表的身份


在 Object 中,方法hashCode是辅助的、有用的方法,主要目的是服务于equals方法。协议是,如果对于两个对象hashCode返回不同的值,equals不能返回 true。

因此,方法hashCodeequals用于建立对象的身份

方法compareTo(在 Comparable 和 Comparator 中)服务于另一个通用目的。它定义对象的顺序,而不是它们的身份

Resume- compareTo定义了对象排序方式,hashCode(与equals一起)定义了对象的身份


再次实践的贡献是,您经常需要对一组对象进行排序,但很少(如果有的话)必须获取一组对象并交叉比较它们的身份

于 2013-03-17T01:07:14.363 回答