私はintの配列のセットを作成しようとしていますが、私がやろうとすると:
HashSet<int[]> s = new HashSet<int[]>();
int a1[] = {1,2,3};
int a2[] = {1,2,3};
s.add(a1);
s.add(a2)
System.out.println(s.size());
この場合、s には 2 つのオブジェクトがありますが、1 つのみであるべきです。注: HashSet< Integer[]> であるかどうかは関係ありません。うまくいきません。
ArrayList< Integer> でこれを実行しようとすると、次のようになります。
HashSet<ArrayList<Integer>> s = new HashSet<ArrayList<Integer>>();
ArrayList<Integer> a1 = new ArrayList<Integer>();
ArrayList<Integer> a2 = new ArrayList<Integer>();
a1.add(1);
a1.add(2);
a1.add(3);
a2.add(1);
a2.add(2);
a2.add(3);
s.add(a1);
s.add(a2)
System.out.println(s.size());
この場合、s は 1 つのオブジェクトを持ちます。
最初のコードでエラーを回避する方法を考え、次のように各配列のハッシュコードをハッシュセットに格納していました。
int a1[] = {0,10083,10084,1,0,1,10083,0,0,0,0};
int a2[] = {1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,1 ,0,2112};
HashSet<Integer> s= new HashSet<Integer>();//hashcodes of each array
s.add(Arrays.hashCode(a1));
s.add(Arrays.hashCode(a2));
System.out.println(Arrays.hashCode(a1));
System.out.println(Arrays.hashCode(a2));
System.out.println(s.size());
最初のケース(1、2、3)では機能しますが、衝突がある場合は機能しないため、衝突を管理する必要があります。だから、私がやっていることは、HashSetを自分で実装していると思います。
HashSet< ArrayList< Integer>> を使用すると、完全に機能します。その場合、Javaは衝突を管理すると思います。
私の質問は、生成されたハッシュコードが ArrayList< Integer> と同じであり、配列のハッシュコードを呼び出すだけで Arrays.hashCode( ...)。
最後に、HashSet< int[]>(または HashSet< Integer[]>) を実行したい場合は、自分で実装する必要がありますか? またはそれを行うためのより良い方法はありますか?
ありがとう。
更新: わかりました、ついに私は完全な答えに達したと思います。@ZiyaoWei と @user1676075 がコメントしたように、 equals が false を返し、ハッシュコードが異なるため、機能しません。しかし、なぜ Java はこのメソッドを (Arrays.equals()、Arrays.hashCode() で) オーバーライドしないので、HashSet< int[]> のようなことができるのでしょうか? 答えは、配列は可変オブジェクトであり、ハッシュコードの一般的な契約に従って、ハッシュコードは可変値に依存できないためです(配列の各要素は可変値です)。可変オブジェクトと hashCode
ここで、hashCode http://blog.mgm-tp.com/2012/03/hashset-java-puzzler/ で可変フィールドを使用し、hashmap で可変キーを使用することについて のわかりやすい説明があります。
私の答えは、 HashSet< int[]> を使用する場合は、配列を持つクラスを作成する必要があり、ハッシュコードと equals を値に依存させたい場合は、メソッド equals() と hashCode() を Arrays でオーバーライドすることです。 .equals() および Arrays.hashCode()。契約に違反したくない場合は、配列を final にするだけです。
みんな、ありがとう!