为什么每次添加新元素时 ArrayList 的 hashCode() 都会更改?
Why does the hashCode() of an ArrayList change every time you add a new element?
根据我对ArrayList
的理解,默认容量是10,当它增长超过10时,它会创建一个新容量的新对象等等..
出于好奇,我输入了以下程序来检查 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());
}
}
}
根据上述情况,当我没有为 ArrayList
设置初始容量时,默认值为 10。
所以在添加第 11 个元素时,它会创建一个新对象并增加 ArrayList
.
的容量
当我打印 ArrayList
对象的哈希码时,它每次都会给出一个新的 hashcode()
。
以下是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()
,因为在那之前不需要创建新对象,但事实并非如此。
ArrayList
的hashCode
是ArrayList
中存储的所有元素的hashCode
的函数,所以容量不变更改时,每当您添加或删除元素或以更改其 hashCode 的方式改变其中一个元素时,它都会更改。
这是 Java 8 的实现(它实际上是在 AbstractList
中实现的):
public int hashCode() {
int hashCode = 1;
for (E e : this)
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
return hashCode;
}
顺便说一句,这是 List
接口的 hashCode()
的 Javadoc 中出现的确切代码:
int java.util.List.hashCode()
Returns the hash code value for this list. The hash code of a list is defined to be the result of the following calculation:
int hashCode = 1;
for (E e : list)
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
List
实施的 hashCode
是 defined in terms of the hashCode
of its elements。这意味着要使 ArrayList
成为符合要求的 List
实现,它的 hashCode
必须 在其内容更改时进行更改。
更一般地说:对于可变对象,hashCode
应该在它们以某种方式改变时改变,而不是 equal
到它们以前的状态。
您似乎假设它使用 Object
的 default hashCode
,但事实并非如此。
此外,即使 ArrayList
没有实现 hashCode
,如果 ArrayList
的默认哈希码(也称为 identity hash code)不会改变内部数组已重新分配,因为 ArrayList
对象本身保持不变,只是内部数组对象(您无法直接访问)将被替换为新对象。
根据我对ArrayList
的理解,默认容量是10,当它增长超过10时,它会创建一个新容量的新对象等等..
出于好奇,我输入了以下程序来检查 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());
}
}
}
根据上述情况,当我没有为 ArrayList
设置初始容量时,默认值为 10。
所以在添加第 11 个元素时,它会创建一个新对象并增加 ArrayList
.
当我打印 ArrayList
对象的哈希码时,它每次都会给出一个新的 hashcode()
。
以下是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()
,因为在那之前不需要创建新对象,但事实并非如此。
ArrayList
的hashCode
是ArrayList
中存储的所有元素的hashCode
的函数,所以容量不变更改时,每当您添加或删除元素或以更改其 hashCode 的方式改变其中一个元素时,它都会更改。
这是 Java 8 的实现(它实际上是在 AbstractList
中实现的):
public int hashCode() {
int hashCode = 1;
for (E e : this)
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
return hashCode;
}
顺便说一句,这是 List
接口的 hashCode()
的 Javadoc 中出现的确切代码:
int java.util.List.hashCode()
Returns the hash code value for this list. The hash code of a list is defined to be the result of the following calculation:
int hashCode = 1;
for (E e : list)
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
List
实施的 hashCode
是 defined in terms of the hashCode
of its elements。这意味着要使 ArrayList
成为符合要求的 List
实现,它的 hashCode
必须 在其内容更改时进行更改。
更一般地说:对于可变对象,hashCode
应该在它们以某种方式改变时改变,而不是 equal
到它们以前的状态。
您似乎假设它使用 Object
的 default hashCode
,但事实并非如此。
此外,即使 ArrayList
没有实现 hashCode
,如果 ArrayList
的默认哈希码(也称为 identity hash code)不会改变内部数组已重新分配,因为 ArrayList
对象本身保持不变,只是内部数组对象(您无法直接访问)将被替换为新对象。