Java 8注释描述

  • 这个方法返回一个对象的哈希码值 (hash code)
  • 支持这个方法有利于散列表 (hash tables),比如在HashMap提供的散列表
  • hashCode方法概要
    • 在任何时候,假如用来对比对象的方法equals没有被修改,那么对同一个对象来说,多次调用hashCode方法应返回相同的整数。这个整数不需要保持一致在同一个表达式的多次调用上
    • 若两个对象是相同的(通过equals方法),那么这两个对象调用hashCode方法将返回相同的整数结果
    • 若两个对象是不同的(通过equals方法),那么这两个对象调用hashCode方法不一定需要返回不同的结果
    • 然而,程序员应该意识到对于不相同的对象,返回不相同的整数结果,可能会提高散列表 (hash tables) 的性能
  • 在一般情况下,hashCode方法确实会为不同的对象返回不同的整数(这个通常是将对象的内存地址转换为整数来实现的,但Java编程语言不需要这种实现技术)

参考Object类hashCode相关文章

方法分析

  • 虽然Java 8中注释说明hashCode方法的返回值跟对象内存地址有关,但实际上,在java 6和7中,它是随机数生成的数字,而在java 8中,它是基于线程有关的随机数和三个确定值确定的(Marsaglia’s xorshift scheme随机数算法)
  • 所以,hashCode方法的返回值与对象的内存地址无关
  • 其次,咱们可以通过JVM启动参数 -XX:hashCode=指定生成方式序号 来改变它的生成方式

为什么重新定义equals方法,就需要重新定义hashCode方法

  • 首先,Java中只是建议重新定义equals方法时,重新定义hashCode方法;实际上,是否需要重新定义hashCode还是取决于具体的使用场景,不是强制必须的
  • 其次,Java中在不仅仅是两个方法重写,最好能够保证当两个对象equals相等时,它们的hashCode也相等
  • 那么,假设不重新定义hashCode又会发生什么呢?如:
    • 在HashMap中,其底层的数据结构采用的是:数组 + 链表(或红黑树)
    • 在分配key在数组的哪个位置时,就需要根据key的hashCode来进行分配
    • 当为两个对象 (equals方法结果为false) 分配位置时,若它们的hashCode相同,那么就会被分配到数组的同一个位置上,形成链表(长度小于8)
    • 此时就会影响到HashMap的查询性能
    • 注意:这只是一种场景,其中的影响绝不仅仅是这一种
  • 结论:这不是必须的,但是最好能够遵循Java的关于重写的建议

重写方法建议参考