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()
を出力するはずですが、そうではありません。
hashCode
のArrayList
は、hashCode
に格納されているすべての要素のArrayList
sの関数であるため、容量が変化しても変化しません。要素を追加または削除するか、hashCodeを変更する方法で要素の1つを変更するたびに変更されます。
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()
このリストのハッシュコード値を返します。リストのハッシュコードは、次の計算の結果として定義されます。
_int hashCode = 1;
for (E e : list)
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
_
hashCode
のList
の実装は その要素のhashCode
で定義 です。これは、ArrayList
が準拠するList
実装であるためには、hashCode
mustコンテンツが変更されたときに変更されることを意味します。
より一般的には、可変オブジェクトの場合、hashCode
は、以前の状態にequal
しないように変更されるたびに変更する必要があります。
default hashCode
of Object
を使用すると想定しているようですが、そうではありません。
さらに、ArrayList
がhashCode
を実装していなくても、ArrayList
のデフォルトのハッシュコード(別名 identity hash code )はArrayList
オブジェクト自体は同じままなので、内部配列が再割り当てされた場合は変更し、内部配列オブジェクト(直接アクセスできない)だけを新しい配列オブジェクトに置き換えます。
これの説明は hashCodeのドキュメント を参照してください。
Equals(Object)メソッドに従って2つのオブジェクトが等しい場合、2つのオブジェクトのそれぞれでhashCodeメソッドを呼び出すと、同じ整数の結果が生成される必要があります。
ArrayList
sの内容が変更されると、それが等しい他のオブジェクトも変更されます。 Object
の契約のこの部分を満たすために、ArrayList
は、内容が変化したときにhashCode
を変更するか、すべてのArrayList
を保持する必要があります同じhashCode
です。それをいくらか有用にするために、彼らは明らかに前者を選びました。これは List
のドキュメント で確認できます。
このリストのハッシュコード値を返します。リストのハッシュコードは、次の計算の結果として定義されます。
int hashCode = 1; for (E e : list) hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
これにより、Object.hashCode()の一般規約で要求されるように、list1.equals(list2)が2つのリスト、list1とlist2のlist1.hashCode()== list2.hashCode()を暗黙的に示すことが保証されます。