我有一个基于哈希的对象集合,例如HashSet
或HashMap
。当hashCode()
的实现可以随时间变化,因为它是从一些可变字段计算出来时,我可以遇到哪些问题?
它如何影响Hibernate?有没有理由为什么hashCode()
默认返回对象的ID是坏的?如果重要的话,所有尚未持久化的对象都有id = 0。
Hibernate映射实体hashCode
的合理实现是什么?一旦设置,ID就是不可变的,但在将实体保存到数据库的时刻却不是这样。
我并不担心具有key = 0的十几个实体的HashSet
的性能。我关心的是我的应用程序和Hibernate是否可以使用ID作为哈希代码,因为ID会在持久化时生成。
答案 0 :(得分:3)
如果同一对象的哈希码随时间变化,则结果基本上是不可预测的。散列集合使用散列码将对象分配给存储桶 - 如果散列代码突然改变,集合显然不知道,因此它可能无法找到现有对象,因为它现在散列到不同的存储桶。
返回一个对象的ID本身并不错,但是如果你们中提到的很多都有id = 0,那么它会降低哈希表的性能:具有相同哈希码的所有对象进入同一个桶,所以你的哈希表现在不比线性列表好。
更新:理论上,只要没有其他人知道它,您的哈希码就会发生变化 - 这正是@bestsss在评论中提到的,即从任何集合中删除您的对象可能持有它并在哈希码更改后再次插入它。实际上,更好的选择是从对象的实际内容字段生成哈希代码,而不是依赖于数据库ID。
答案 1 :(得分:3)
如果将对象添加到基于散列的集合中,然后改变其状态以便更改其哈希码(并且暗示可能是.equals()
调用中的行为),您可能会看到效果,包括但不限于:
这肯定不是你想要的。因此,我建议仅使用不可变字段来创建哈希码。这通常通过创建字段final
并在构造函数中设置它们来完成。
答案 2 :(得分:1)
答案 3 :(得分:0)
放入后不要更改基于散列的集合中元素的哈希码。
许多程序员陷入了陷阱。 您可以认为哈希码是集合中的地址,因此在将元素放入集合后,您无法更改元素的地址。
答案 4 :(得分:0)
Javadoc明确表示内置集合不支持此功能。所以不要这样做。