2013-05-20 2 views
8

を同じ値を持つ配列を追加し、事は私が何をしようということである。私はint型の配列のセットを作成しようとしている重複するアイテムにHashSetの結果に

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であるかどうかは関係ありません<整数[]>。それだけでは機能しません。今

私はArrayListの<整数でこれを実行しようとした場合>、のようなもの:

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()); 

は、その後の1つのオブジェクトがあります。

Iは最初のコードのエラーを回避する方法と、次のようにHashSetの各配列のハッシュコードを格納したものの:これは最初のケース(1,2,3)のために働く

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()); 

しかし衝突がある場合は機能しませんので、衝突を管理する必要があります。だから、私は自分でHashSetを実装していると思います。

With HashSet < ArrayList <整数>>完全に動作します。私はjavaがその場合の衝突を管理すると思います。生成されたハッシュコードは、ArrayListの<整数の場合と同じである>と配列のハッシュコードを呼び出すことで簡単に計算できるのであればJavaは> [] HashSetの<のint []>やHashSetの<整数を管理することはできませんなぜ私の質問がある

Arrays.hashCode(...)。

最後に、私がHashSet < int []>(またはHashSet < Integer []>)を実行したい場合は、自分で実装する必要がありますか?それとももっと良い方法がありますか?

ありがとうございました。

更新日:最後に、私は完全な答えになったと思います。 @ ZiyaoWeiと@ user1676075がコメントしたように、equalsはfalseを返し、hashcodesは異なるため、動作しません。しかし、なぜjavaはこのメソッド(Arrays.equals()、Arrays.hashCode())をオーバーライドしないので、HashSet < int []>のようなことができますか?その答えは、配列が可変オブジェクトであり、hashcodeの一般的な規約に従って、hashcodeは変更可能な値(配列の各要素は変更可能な値です)に依存できないためです。ハッシュマップでMutable objects and hashCode

ここでのhashCode http://blog.mgm-tp.com/2012/03/hashset-java-puzzler/で変更可能なフィールドを使用しての素敵な説明や変更可能なキーAre mutable hashmap keys a dangerous practice?

私の答えは、あなたがHashSetの< int型を使用したい場合は、[]>あなたが持つクラスを作成する必要があり、そのハッシュコードと等価が値に依存するようにするには、equals()メソッドとhashCode()をArrays.equals()とArrays.hashCode()でオーバーライドします。契約に違反したくない場合は、配列を最後にしてください。

ありがとうございました!

+0

下記のZiyaoの回答をご覧ください。つまり、a.hashCode()がb.hashCode()と一致するかどうかを確認してください。私は彼らが平等ではないと賭けるでしょう。 –

+0

[Javaで配列のセットを作る方法は?](http://stackoverflow.com/questions/9841934/how-to-make-a-set-of-array-in-java) – Raedwald

答えて

8

それは一日の終わりに衝突とは何の関係もありません:

a1.equals(a2) == false 

が等しくないので、Setが異なるとしてそれらを扱います。

注:JavaのArrayequalsメソッドをObjectから上書きしません。 ?E:セットは、その(E == nullのE2 == nullを一切要素e2が含まれていない場合

そしてSetadd以来

正式

それ以上のものとして定義されるが、このセットに指定された要素eを追加します.equals(E2))

さは適切にいくつかの契約に違反することなく、あなたの要件を(Arrays.equalsで要素を比較)を満たす可能性があるSetを実装することは不可能であると思われます。

+0

これはJavaの欠陥です。 'Array'は私の見解で' equals'をオーバーライドすべきです。私は効果的なJavaでそれがなぜそうでないのか説明する参照を見つけることができません。 –

+0

@PhilipWhitehouse合意して、私はトピックを説明するものは何も見つかりません。 –

+0

こんにちは、ありがとう。私はそれが衝突と関連していると思います。 HashSet を使用する場合は、hashCodeメソッドとequalsメソッドをオーバーライドする必要があります。なぜなら、同じハッシュコードを持っていれば、equalsメソッドを使って同じかどうかを知る必要があるからです(私が知っている通り、私が間違っていたら私を修正してください!)。あなたが正しいと思うのは、javaが配列のequalsメソッドをオーバーライドしないからです。 :) – voodoo14

1

HashSetが同じオブジェクトを2回挿入しているかどうかを判断するために、HashSetが.equals()比較を使用するためです。 Listの場合、同じ内容の同じ基本タイプ(ArrayListなど)の2つのリストが、同じ順序で同じものとして比較されます。したがって、同じオブジェクトを2回挿入するようにHashSetに指示しています。一回のインスタンスで一回しかかかりません。

アレイで同じ操作を実行しようとすると。 Javaの配列比較の詳細については、この記事を参照してください:equals vs Arrays.equals in Java 2つの配列を挿入すると、デフォルトの.equals()は同じオブジェクトであるかどうかをテストします。したがって、それは失敗する。

関連する問題