9

私は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 にするだけです。

みんな、ありがとう!

4

2 に答える 2

1

The reason the HashSet> works is because the HashSet will use .equals() comparison to decide if you're inserting the same object twice. In the case of List, two lists of the same base type (e.g. ArrayList) with the same content, in the same order, will compare as equal. Thus you're telling the HashSet to insert the same object twice. It only takes a single instance once.

When you try to do that same operation with an array. See this post: equals vs Arrays.equals in Java for more details about array comparisons in Java. When you insert two arrays, the default .equals() tests if they are the same object, which they are not. Thus it fails.

于 2013-05-20T21:05:49.147 に答える