Javaのセットは、重複する要素を含まない、または正確にするために、e1.equals(e2)を含まない要素ペアです。 nullはセットで許可されています。セットは、セット内の要素の順序を保証することはできません。
設定する要素を追加すると、指定された要素が存在しない場合、追加は成功します。つまり、要素E1がセットに存在しない場合(E == null?e1 == null:e.queals(e1))、e1をセットに追加できます。
以下は、例として設定された実装クラスのハッシュセットを示し、実装を繰り返さないセットの原則を簡単に紹介します。
パッケージcom.darren.test.overide; public class customstring {private string value; public customstring(){this( "");} public customstring(string value){this.value = value;}}} java.util.hashset; import java.util.hashset; import java.util.util.set; public class hashsettest {public static void main(string [] args){string a = new string( "a"); string b = new string( "a"); custom custint( "b"); customstring d = new customstring( "b = new string(" a "); string b = new String(" a "); string b = new string(" a "); customString( "b"); system.out.println( "a.equals(b)==" + a.equals(b)); system.out.println( "c.equals(d)==" + c.equals(d)); set <object> set = new hashset <object>(a); set.add(b); set.add(c); set.add(d); system.out.println( "set.size()==" + set.size()); for(object object:set){system.out.out.out.println(object);}}}}}操作結果は次のとおりです。
A. equals(b)== true c.equals(d)== false set.size()== 3 com.darren.test.overide.customstring@2c39d2 com.darren.test.overide.customstring@5795ce
たぶん、あなたは鍵を見たことがあるかもしれません、そうです、それは等しい方法です。これを言うのはまだ不適切ですが、正確には、それは平等とハッシュコードのメソッドでなければなりません。なぜそれを言うのですか?カスタムストリングクラスを変更してテストしましょう。
パッケージcom.darren.test.overide; public class customstring {private string value; public customstring(){this( "");} public customstring(} public customstring(string value){this.value = value;}@Override public boolean equals(オブジェクトOBJ){if(this == obj){return true;} else if(obj instance intanceof customstring) obj; return customstring.value.equals(value);} else {return false;}}}}テスト結果:
A. equals(b)== true c.equals(d)== true set.size()== 3 com.darren.test.overide.customstring@12504e0 com.darren.test.overide.customstring@1630eb666
今回の等しいリターン値は当てはまりますが、セットのサイズはまだ3です。
変え続けましょう
パッケージcom.darren.test.overide; public class customstring {private string value; public customstring(){this( "");} public customstring(string value){this.value = value;}@override public int hashcode(){// return super.hashcode(); 1;}}を返します結果をもう一度見てください:
A. equals(b)== true c.equals(d)== false set.size()== 3 com.darren.test.overide.customstring@1 com.darren.test.overide.customstring@1 a
HashCodeメソッドのみを書き換え、Equals Methodを書き換えません
最後に、それを変更します
パッケージcom.darren.test.overide; public class customstring {private string value; public customstring(){this( "");} public customstring(} public customstring(string value){this.value = value;}@Override public boolean equals(オブジェクトOBJ){if(this == obj){return true;} else if(obj instance intanceof customstring) obj; return customstring.value.equals(value);} else {return false;}}@override public int hashcode(){// return super.hashcode(); 1;}}を返します最終結果:
A. equals(b)== true c.equals(d)== true set.size()== 2 com.darren.test.overide.customstring@1 a
わかりました、Equals MethodとHashcodeメソッドを書き換えて、原則を参照する必要があることが証明されています。
java.lnag.objectのハッシュコードの慣習:
1.アプリケーションの実行中、オブジェクトの等式方法を比較するために使用される情報が変更されていない場合、ハッシュコード法はオブジェクト上で複数回呼び出され、一貫して同じ整数を返す必要があります。
2。2つのオブジェクトがEquals(Objecto)メソッドに従って等しい場合、2つのオブジェクトのいずれかのハッシュコードメソッドを呼び出す必要がある場合、同じ整数結果を生成する必要があります。
3. 2つのオブジェクトがEquals(objecto)メソッドに従って等しくない場合、2つのオブジェクトのいずれかのハッシュコードメソッドが呼び出され、整数の結果は必要ありません。しかし、それが異なる場合は、ハッシュテーブルのパフォーマンスを改善する可能性があります。
ハッシュセットでは、ハッシュセット層がハッシュマップを使用してデータを保存するため、ハッシュマップ層によって基本操作が実装されます。ハッシュセットに要素を追加するとき、最初に要素のハッシュコード値を計算し、次にこれ(要素のハッシュコード)%(ハッシュマップコレクションのサイズ) + 1を使用して、この要素のストレージ位置を計算します。この位置が空の場合は、要素を追加します。空でない場合は、Equalsメソッドを使用して、要素が等しいかどうかを比較し、等しい場合はそれを追加しないでください。
以下は、ハッシュセットのソースコードの一部です。
パッケージjava.util;パブリッククラスのハッシュセット<e>拡張抽象セット<e>実装<e> set <e>、cloneable、java.io.serializable {static final long serialversionuid = -502474444067133321676l;プライベートトランジェントハッシュマップ<e、オブジェクト>マップ; //仮想オブジェクトオブジェクトをハッシュマップの値として定義し、このオブジェクトを静的な最終として定義します。 private static final object present = new object();/***デフォルトのパラメーターレスコンストラクターは、空のハッシュセットを構築します。 * *実際、基礎となる層は空のハッシュマップを初期化し、デフォルトの初期容量16と0.75の負荷係数を使用します。 */public hashset(){map = new hashmap <e、object>();}/***指定されたコレクションの要素を含む新しいセットを作成します。 * *実際の基礎層は、デフォルトの負荷係数0.75を使用し、指定された *コレクションのすべての要素の初期容量を含めてハッシュマップを作成するのに十分です。 * @param cその中の要素は、このセットのコレクションに保存されます。 */public hashset(collection <extends e> c){map = new hashmap <e、object>(math.max((int)(int)(c.size()/。75f) + 1、16); addall(c);}/***指定された初期容量と荷重ファクターを使用して空のハッシュセットを構築します。 * *実際の基礎層は、対応するパラメーターを備えた空のハッシュマップを構築します。 * @param initialcapacity初期容量。 * @Param LoadFactorロードファクター。 */public hashset(int initialcapacity、float loadfactor){map = new hashmap <e、object>(initialcapacity、loadfactor);}/***指定された初期容量で空のハッシュセットを構築します。 * *実際、基礎となる層は、対応するパラメーターと0.75の負荷係数を備えた空のハッシュマップを構築します。 * @param initialcapacity初期容量。 */public hashset(int initialcapacity){map = new hashmap <e、object>(initialcapacity);}/***指定されたInitial -capacityおよびloadFactorを使用して新しい空のリンクハッシュコレクションを作成します。 *このコンストラクターはパッケージアクセス許可であり、一般に公開されていません。実際には、LinkedHashsetの単なるサポートです。 * *実際、基礎となる層は、指定されたパラメーターを使用して空のLinkedhashmapインスタンスを構築します。 * @param initialcapacity初期容量。 * @Param LoadFactorロードファクター。 * @paramダミータグ。 */hashset(int initialcapacity、float loadfactor、boolean dummy){map = new linkedhashmap <e、object>(initialcapacity、loadfactor);}/***このセットの要素を反復する繰り返しを返します。リターン要素の順序は具体的ではありません。 * *基礎となる層は、実際には、基礎となるハッシュマップのキーセットを呼び出して、すべてのキーを返します。 *ハッシュセットの要素は見ることができますが、基礎となるハッシュマップのキーに保存され、値は静的な最終オブジェクトオブジェクトによって識別されます。 * @return iteratorこのセットの要素を繰り返します。 */@Override public Iterator <e> iterator(){return map.keyset()。iterator();}/***このセットの要素の数(セットの容量)を返します。 * *基礎となるレイヤーは、実際にはハッシュマップのサイズ()メソッドを呼び出して、エントリ数を返し、セット内の要素の数を取得します。 * @returnこのセットの要素の数(セットの容量)。 */@Override public int size(){return map.size();}/***このセットに要素が含まれていない場合はtrueを返します。 * *基礎となるレイヤーは、実際にはハッシュマップの呼び出し()のISEMPTY()であり、ハッシュセットが空であるかどうかを判断します。 * @returnこのセットに要素が含まれていない場合はtrueを返します。 */@Override public boolean isempty(){return map.isempty();}/***このセットに指定された要素が含まれている場合はtrueを返します。 *より具体的には、このセットが満たすe要素が含まれている場合にのみ、trueが返されます(o == null?e == null:o.equals(e)) *。 * * HashMapへの基礎となる実際の呼び出しのcontainseyは、指定されたキーが含まれているかどうかを決定します。 * @param oこのセットの要素の存在がテストされています。 * @returnこのセットに指定された要素が含まれている場合はtrueを返します。 */@Override public boolean contains(object o){return map.containskey(o);}/***指定された要素がこのセットに含まれていない場合は、指定された要素を追加します。 *より具体的には、このセットに満たされる要素E2が含まれていない場合(e == null?e2 == null:e.equals(e2)) *、指定された要素eがこのセットに追加されます。 *このセットに既に要素が含まれている場合、コールはセットを変更せず、falseを返します。 * *基礎となる層は、実際に要素をハッシュマップにキーとして配置します。 * HashmapのPut()メソッドはキー値ペアを追加するため、Hashmapの新しいエントリのキーがコレクションの元のエントリのキーと同じである場合(HashCode()等しい比較を介してTRUEも返します)。 *したがって、既存の要素がハッシュセットに追加された場合、新しく追加されたコレクション要素はハッシュマップに入れられず、 *元の要素は変更されません。 *このセットに追加される@param e要素。 * @returnこのセットに指定された要素が含まれていない場合はtrueを返します。 */@Override public boolean add(e){return map.put(e、present)== null;}/***このセットに指定された要素が存在する場合、削除されます。 *より具体的には、このセットに満たされる要素Eが含まれている場合(o == null?e == null:o.equals(e))、 *はそれを削除します。このセットに既に要素が含まれている場合はtrueを返します(または、このセットが呼び出しのために変更された場合はtrue)。 (呼び出しが戻ったら、このセットには要素が含まれなくなりました)。 * *基礎となる層は、実際には、HashMapの削除方法を呼び出して、指定されたエントリを削除します。 * @param oこのセットに存在する場合に削除する必要があるオブジェクト。 * @returnセットに指定された要素が含まれている場合はtrueを返します。 */@Override public boolean remove(object o){return map.remove(o)== spresent;}/***このセットからすべての要素を削除します。この呼び出しが戻った後、セットは空になります。 * *基礎となる層は、実際にはハッシュマップの明確な方法を呼び出して、エントリのすべての要素をクリアします。 */@Override public void clear(){map.clear();}}要約します
上記は、重複値のハッシュセット除去の原理の分析に関するこの記事のすべての内容です。私はそれが誰にでも役立つことを願っています。興味のある友人は、このサイトの他の関連トピックを引き続き参照できます。欠点がある場合は、それを指摘するためにメッセージを残してください。このサイトへのご支援をありがとうございました!