【♨Java基础】hashCode()和equals()方法及使用规范

阿里巴巴Java开发手册规定

  • 只要重写 equals,就必须重写 hashCode。
  • 因为 Set 存储的是不重复的对象,依据 hashCode 和 equals 进行判断,所以 Set 存储的对象必须重写这两个方法。
  • 如果自定义对象做为 Map 的键,那么必须重写 hashCode 和 equals。

计算hashCode的注意事项

1)不能包含equals方法中没有的字段,否则会导致相等的对象可能会有不同的哈希值。(即只对equals方法中的字段进行操作)

2)String对象和Bigdecimal对象已经重写了hashcode方法,这些类型的值可以直接用于重写hashcode方法;

3)大多数计算过程中会使用到31,31是个神奇的数字,任何数n*31都可以被jvm优化为(n<<5)-n,移位和减法的操作效率比乘法的操作效率高很多

4)Joshua Bloch在他的著作《Effective Java》中提出了一种简单通用的hashCode算法:

① 初始化一个整形变量,为此变量赋予一个非零的常数值,比如int result = 17;

② 如果是对象应用(例如有String类型的字段),如果equals方法中采取递归调用的比较方式,那么hashCode中同样采取递归调用hashCode的方式。否则需要为这个域计算一个范式,比如当这个域的值为null的时候(即 String a = null 时),那么hashCode值为0

由于areaCode和localNumber都是用来区分类TantanitReaderPhone的重要字段,所以根据这两个字段来计算哈希值。这两个字段都是String类型,直接调用String自带的hashCode方法(areaCode和localNumber假定都不为null)。

equals()的设计原则

  • 对称性:如果x.equals(y)返回是true,那么y.equals(x)也应该返回是true。
  • 反射性:x.equals(x)必须返回是true。
  • 类推性:如果x.equals(y)返回是true,而且y.equals(z)返回是true,那么z.equals(x)也应该返回是true。
  • 一致性:如果x.equals(y)返回是true,只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是true。
  • 非空性:x.equals(null),永远返回是false;x.equals(和x不同类型的对象)永远返回是false。

hashCode()的设计原则

  • 在一个Java应用的执行期间,如果一个对象提供给equals做比较的信息没有被修改的话,该对象多次调用hashCode()方法,该方法必须始终如一返回同一个integer。
  • 如果两个对象根据equals(Object)方法是相等的,那么调用二者各自的hashCode()方法必须产生同一个integer结果。
  • 并不要求根据equals(java.lang.Object)方法不相等的两个对象,调用二者各自的hashCode()方法必须产生不同的integer结果。然而,程序员应该意识到对于不同的对象产生不同的integer结果,有可能会提高hash table的性能。

 

参考:

 

posted @ 2023-03-23 09:12  残城碎梦  阅读(74)  评论(0编辑  收藏  举报