ConcurrentHashMapHashMap使用equals()/hashCode()的关键实例.

几十年来,在相当多的场合,我错过了提供不同的equals/hashCode实现的可能性.不能这样做意味着您要么必须使用排序映射(允许您设置Comparator,代价是SortedMap较差的性能特性),要么您必须使用不同的对象作为您的键,例如,通过创建提供其自己的equals/hashCode实现的键包装实例.

在后一种情况下,需要 for each 键创建另一个对象具有明显的内存和性能影响.(在我看到的当前情况下,这意味着在高峰时间每秒创建数十万个额外的对象实例--这是性能最重要的地方.)

这似乎是一项微不足道且安全的更改,在需要的情况下具有巨大的性能优势.

at least version 1.1年以来,.NET一直在为其Dictionary提供这一服务.那么,为什么Java没有这样做,有什么好的技术原因吗?

推荐答案

这是作为Java 1.2.2和其他版本的RFE请求的,但从未实现并最终关闭.https://bugs.openjdk.org/browse/JDK-4269596

约书亚·布洛赫在1999年的分析是:

在设计集合框架时,我们仔细考虑了是否包含对自定义equals/hashCode方法的支持.最后,我们拒绝了它,理由是增加了复杂性,并与其他设计决策不一致.特别是,List、Set和Map对象可以独立于其表示形式进行比较的决定与对自定义equals方法的支持不一致.

此外,完全支持定制的equals方法可能有些过分了.在99%的情况下,当开发人员想要一个具有自定义equals方法的集合时,所需的equals方法是元素标识.这建议了另一种解决方案,即提供一个或两个基于身份而不是平等的特殊目的实现.当然,这些实现不会是"领域的好公民",因为它们不能与其他集合进行适当的比较.(您会使用哪种等于方法?)然而,这并非没有先例.通过指定不"与等于一致"的比较器,可以生成违反Map/Set约定的SortedMap/Set.

我将开放此RFE来跟踪对特殊用途、基于身份的SET和Map实现的支持.

最后的 comments (2011年)指出,基于身份的用例have been通过IdentityHashMap等解决.

如果你想深入了解这些问题,你会发现其中有许多相关的问题.


话虽如此,如果您想要一个允许您使用不同于键类型实现的hashCodeequals的Java哈希表实现,有第三方库支持这一点.例如,ApacheCommons集合AbstractHashedMap(javadoc).这个问答中还列出了其他可能性:Custom hashcode/equals operation for HashMap.

Java相关问答推荐

CriteriaQuery with max

使用Java Streams API比较两个不同的Java集合对象和一个公共属性

在现代操作系统/硬件上按块访问数据值得吗?

JDK22执行repackage of goal org. springframework. boot:spring—boot—maven—plugin:3.2.3:repackage failed:unsupported class file major version 66—>

需要一个找不到的jakarta.sistence.EntityManager类型的Bean

Java记录的不同序列化/反序列化

什么是Java原子属性的正确getter和setter

使用UTC时区将startDatetime转换为本地时间

使用Jolt将字段转换为列表

使用存储在字符串变量中的路径目录打开.pdf文件

在macOS上读取文件会导致FileNotFound,即使文件存在(并且具有权限)

如何在Record Java中使用isRecord()和RecordComponent[]?

判断重复的两个二维表算法?

Java嵌套流查找任意值

Java KeyListener不工作或被添加

获取所有可以处理Invent.ACTION_MEDIA_BUTTON Android 13 API33的Android包

org.springframework.web.HttpRequestMethodNotSupportedException:请求方法';帖子';不支持

为什么Instant没有从UTC转换为PostgreSQL的时区?

java中的网上购物车解析错误

类型安全:从 JSONArray 到 ArrayList> 的未经判断的转换