Java周二生效! 遵守`hashCode`合同

今天的话题恰好与上周的话题一致。 这周我们在谈论hashCode功能。 就像等于上周我们讨论的函数,这种方法也有一个合同,尽管比较简单,但应遵循。 与签名一样,不带参数并返回整数。 因此,让我们签订合同:

  • 如果未更改对象,则从函数返回的值应保持不变。如果两个对象实际上相等,则它们的哈希码必须相同。(这更多是一种非要求)给定两个对象实际上是不相等的不需要具有不同的哈希码值。

这样就可以看到哈希码与平等息息相关。 第二个要求是最被打破的要求。 如果您未实现哈希码函数,则两个有效等效的对象可能不会具有该函数返回的相同值。 因此,让我们看一个例子:

Map<Address, String> addressBook = new HashMap<>();
addressBook.put(new Address("123","Foggy Lane" "Made Up City", "USA"), "James");
addressBook.get(new Address("123","Foggy Lane" "Made Up City", "USA"));

给定上面的示例,预期第三行将返回“ James”,但是,如果哈希代码功能编写不正确,它将返回空值。

因此,让我们编写最简单的合法的哈希码函数:

@Override
public int hashCode() {
  return 42;
}

是的,根据合同,这是完全有效的哈希码函数。 如果在同一对象上多次调用它,则总是返回相同的事物;对于功能上等同的对象,它返回相同的值;对于两个功能上不等同的对象,它返回相同的哈希码也可以。 但是,即使它符合合同,返回的值也没有任何变化,这是一个可怕的想法,并且可能导致性能大大下降。 例如,就性能而言,上述哈希码功能将有效地将HashMap转换为链接列表。

必须有一个更好的方法,而且确实存在。有效的Java为我们提供了创建固体哈希码函数的方法。

  1. 声明整型命名结果并将其初始化为对象的第一个有效字段的值(提醒“有效字段”是指在两个对象相等时参与决策的字段),如步骤2中所计算。For every remaining significant field, do the following计算一个整型该字段的哈希码如果该字段是原始字段,则使用盒装版本的字段进行计算hashCode功能。 例如:Double.hashCode(值)If the field is an object reference, call 整型o that object's hashCode功能。 对于null,请使用值0如果其为数组,则将每个重要元素视为一个单独的字段或使用Arrays.hashCode如果它们都是重要的。Combine the hash code you just calculated with the 结果 as follows: 结果 = 31 * 结果 + newFieldHashcode返回结果

如果正确遵循上述算法,则应该计算出一个可靠的哈希码。 该算法的优点是操作顺序很重要,因此可以实现更好的分配。 乘以31是很好的,因为它是一个奇数素数。 奇数有助于整数溢出,而质数部分只是因为质数很酷。 在所有现实中,听起来好像已经成为一种标准。 让我们来看看我们的新地址hashCode函数。

@Override
public int hashCode() {
  int result = streetAddress.hashCode();
  result = 31 * result + road.hashCode();
  result = 31 * result + country.hashCode();
  return result;
}

相当简单,但有效。 有没有更简单的方法来编写这些功能? 当然。 一个例子是使用Objects.hashCode(significantField1,significationField2,...)。 很好,因为它是一行hashCode功能。 不利的一面是,它的性能比之前的示例差。 但我认为最好的办法是使用Lombok之类的东西。 龙目岛通过它实现了@EqualsAndHashCode注解。 龙目岛(Lombok)的维护者非常乐意迫使等于和hashCode一起。

最后,让我们讨论一些要记住的事情哈希码:

  • 始终覆盖哈希码当您覆盖等于包括所有正在使用的值等于作为计算的一部分哈希码。Don't share outside the function how the hash code is calculated, it unnecessarily can tie you to a sub-par implementation。

from: https://dev.to//kylec32/effective-java-tuesday-obey-the-hashcode-contract-3onl

发布了0 篇原创文章 · 获赞 0 · 访问量 634

猜你喜欢

转载自blog.csdn.net/cunxiedian8614/article/details/105691244