为什么每次添加新元素时,ArrayList 的 hashCode() 都会发生变化?

2022-09-02 02:29:15

根据我的理解,默认容量为10,当它增长到10以上时,它将创建一个具有新容量的新对象,依此类推。ArrayList

因此,出于好奇,我键入了以下程序来检查对象:hashcode()ArrayList

public class TestCoreJava {

    public static void main(String [] args){

        ArrayList al = new ArrayList();

        for(int i=0;i<15;i++){

            al.add("Temp"+i);
            System.out.println("Hashcode for "+i+" element "+al.hashCode());
        }
    }
}

根据上述情况,当我不设置默认值的初始容量时,默认值将为10。因此,在添加第 11 个元素时,它将创建一个新对象并增加 的容量。ArrayListArrayList

当我打印对象的哈希码时,它每次都会给出一个新的。ArrayListhashcode()

以下是 o/p:

Hashcode for 0 element 80692955
Hashcode for 1 element -1712792766
Hashcode for 2 element -1476275268
Hashcode for 3 element 1560799875
Hashcode for 4 element 1220848797
Hashcode for 5 element -727700028
Hashcode for 6 element -1003171458
Hashcode for 7 element -952851195
Hashcode for 8 element 607076959
Hashcode for 9 element 1720209478
Hashcode for 10 element -6600307
Hashcode for 11 element -1998096089
Hashcode for 12 element 690044110
Hashcode for 13 element -1876955640
Hashcode for 14 element 150430735

根据默认容量的概念,在第10个元素之前,它应该已经打印出来,因为在此之前不需要创建新对象,但事实并非如此。hashcode()


答案 1

of 是 存储在 中的所有元素的 s 的函数,因此当容量更改时,它不会更改,每当您添加或删除元素或以更改其哈希代码的方式改变其中一个元素时,它都会更改。hashCodeArrayListhashCodeArrayList

这是Java 8实现(它实际上是在 中实现的):AbstractList

public int hashCode() {
    int hashCode = 1;
    for (E e : this)
        hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
    return hashCode;
}

顺便说一句,这是出现在接口的Javadoc中的确切代码:hashCode()List

int java.util.List.hashCode()

返回此列表的哈希代码值。列表的哈希代码被定义为以下计算的结果:

int hashCode = 1;
for (E e : list)
    hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());

答案 2

实现是根据其元素的哈希代码定义的。这意味着,要成为一个符合要求的实现,它必须在其内容发生变化时进行更改。hashCodeListArrayListListhashCode

更一般地说:对于可变对象,每当它们以一种不会达到先前状态的方式发生变化时,它们就应该改变。hashCodeequal

您似乎假设它使用 的默认哈希代码 ,但事实并非如此。Object

此外,即使没有实现,如果重新分配内部数组,则 的默认哈希代码(也称为标识哈希代码)也不会更改,因为对象本身保持不变,只有内部数组对象(您无法直接访问)将被替换为新的数组对象。ArrayListhashCodeArrayListArrayList