数组是否固有hashCode()?以基本类型数组为键的集合哈希码问题
关于数组哈希码的几个关键问题解答
让我逐个帮你拆解这些Java数组相关的常见坑点:
问题1:数组是否拥有固有的hashCode()方法?
是的,所有数组(不管是基本类型数组还是引用类型数组)都继承了根类Object的hashCode()方法,但必须划重点:数组并没有重写这个方法。也就是说,数组调用hashCode()时,返回的是Object类原生的、基于对象内存地址的哈希值,和数组里的实际内容完全无关。
问题2:以基本类型数组为键的HashSet/HashMap会使用哪种哈希码?
因为数组没有重写hashCode(),所以这些集合类会直接使用数组对象的内存地址哈希值。这会导致一个很容易踩的坑:比如你创建两个内容完全相同的int[]数组:
int[] arr1 = {1, 2, 3}; int[] arr2 = {1, 2, 3};
把它们放进HashSet<int[]>里,会被当成两个独立的元素;用它们作为HashMap的键时,也会被识别为不同的键——哪怕数组内容一模一样,因为它们是不同的对象,内存地址不同,哈希码自然也不同。
问题3:Arrays类的静态hashCode(...)方法是基本类型数组的重写实例方法吗?
完全不是。Arrays类提供的hashCode(int[])、hashCode(char[])这些静态方法,是独立的工具方法,数组本身并没有把这些方法实现为自己的实例方法来重写Object的hashCode()。
举个例子,你不能这么用:
int[] arr = {1, 2}; arr.hashCode(); // 这还是调用Object的hashCode,返回内存地址哈希
如果想要得到基于数组内容的哈希值,必须手动调用静态方法:
Arrays.hashCode(arr); // 这个才会根据数组里的元素计算哈希
额外补充
为什么Java要这么设计?其实数组是JVM里的特殊对象,虽然继承了Object,但并没有像String、ArrayList这些类一样重写hashCode()和equals()方法。如果想要让集合类基于数组内容来判断相等性,你有几个选择:
- 用
List代替数组(比如List<Integer>代替int[]),List已经重写了hashCode()和equals() - 自定义一个包装类,把数组作为成员变量,然后重写
hashCode()和equals()方法,基于数组内容实现 - 使用第三方工具类来辅助(比如提供数组内容哈希和相等判断的工具)
内容的提问来源于stack exchange,提问作者John McClane
相关产品推荐
相关产品推荐

