だから私は別のカスタムクラスの学生のセットを持つカスタムクラスクラスを持っています。したがって、次のようになります。
public class Class {
private Set<Student> students;
// other methods
}
今度は、セットの学生に多くの学生を追加および削除します。また、すでにセットの学生の学生のプライベートフィールドの多くを変更します。
質問:これを最適に実装するには、どのデータ構造を使用する必要がありますか?セットstudentのStudentオブジェクトのプロパティを変更する(それによってハッシュコードを変更する)ので、代わりにArrayListを使用する必要がありますか?
これを最適に実装するには、どのデータ構造を使用する必要がありますか?セットstudentのStudentオブジェクトのプロパティを変更する(それによってハッシュコードを変更する)ので、代わりにArrayListを使用する必要がありますか?
セット要素のハッシュコードが変更される可能性がある場合は、HashSet
を使用しないでください。 (そうすると、データ構造が壊れ、セット内の要素が失われる可能性があります。)
しかし、ArrayList
も使用する必要があるとは思えません。なぜなら、hashcode()
がオブジェクトの変更に敏感である場合、equals(Object)
もそうなる可能性が高いからです。つまり、contains(...)
や同様のメソッドはオブジェクトを見つけることができません。
Map
型を使用し、キーとして「学生識別子」を使用する必要があると思います。
(hashcode
とequals
をオーバーライドして、2つのオブジェクトが同じIDを持つことを意味するようにすることもできます。ただし、equals(Object)
は他の目的には使用できません。)
ArrayList
とHashSet
の動作に関しては、これらは完全に異なるクラスです。
ArrayList
重複を検証しません。get()
はO(1)
ですcontains()
はO(n)
ですが、エントリの順序は完全に制御できます。
_ get add contains next remove(0) iterator.remove
ArrayList O(1) O(1) O(n) O(1) O(1) O(1)
_
スレッドセーフではありません。スレッドセーフにするには、Collections.synchronizedList(...)
を使用する必要があります。
HashSet
は、重複がないことを保証します。O(1)
contains()
メソッドを提供しますが、順序は保持されません。
_ add contains next notes
HashSet O(1) O(1) O(h/n) h is the table
_
Collections.synchronizedSet(...)
を使用する必要があります。コードに重複データがある場合は、ArrayListを使用する必要があります。それ以外の場合は、以下に示すようにハッシュセットを使用できます。したがって、コードで重複値が必要ない場合は、リストの代わりにセットを使用します。これにより、セットのパフォーマンスが大幅に向上します(O( n)対O(n ^ 2)(リストの場合)。重複を回避することがセットの目的であるため、これは正常です。
public static void main(String [] args){
ArrayList arr =new ArrayList();
arr.add("Hello");
arr.add("is");
arr.add("Hello");
System.out.println(arr); //As we are using Arraylist therefore
//the duplicate elements are allowed therefore
//"Hello" is not removed in the output
}
public static void main(String [] args){
HashSet arr =new HashSet();
arr.add("Hello");
arr.add("is");
arr.add("Hello");
System.out.println(arr); //As we are using Hashset therefore
//the duplicate elements removed therefore
//"Hello" is removed in the output
}
場合によります。あなたが学生について話しているので、idやrollnoのようなユニークなものがあるに違いありません。はいの場合、ハッシュコードメソッドをオーバーライドし、IDに基づいてハッシュコードを実装します。その後、studentの他のプロパティを変更しても、ハッシュコードに影響はありません。
セットまたはリストを選択するかどうかは、要件によって異なります。このリンクを読むと、セットとリストの違いが明確になります
セットとリストの違いは何ですか?
また、セット内のオブジェクトを使用している場合は、ハッシュコードとequalsメソッドの両方をオーバーライドして、制御できるようにすることができます。独自性のはあなたの手にあります。
あなたの要件から、私は最良の構造はマップであるべきだと思いました。実際に基礎となるSetは、内部のMap構造を使用します。また、ルックアップを改善するために、equalsメソッドのオーバーライドにも注意する必要があります。また、setとarraylistは、ターゲットオブジェクトを検索するために、検索アルゴリズムを使用する必要があるため、期待したほど効率的ではありません(特に、非常に大規模なコレクションの状況で)。マップでさえいくらかのスペースを浪費しますが、IDが何らかのプリミティブ型である場合は、 Troveライブラリ でマップ実装のプリミティブ型を検討できます。
質問:これを最適に実装するには、どのデータ構造を使用する必要がありますか?セットstudentのStudentオブジェクトのプロパティを変更する(それによってハッシュコードを変更する)ので、代わりにArrayListを使用する必要がありますか?
間違いなく、hashCodeまたはequalsで使用される値を変更する場合、HashMapまたはHashSetを使用することはできません。
あなたはあなたがたくさん削除して追加したいと言っています。問題は、それを連続的に実行するか、ランダムに(インデックスに基づいて)実行するかです。追加する場合は、順番に削除してください。間違いなく最良の選択はLinkedListです。オブジェクトにランダムにアクセスする場合は、ArrayListの方がはるかに効率的です。
HashSet
などのハッシュコレクションの場合、キーはimmutable
である必要があります。ハッシュセットは、内部でハッシュを使用して、オブジェクトを格納するバケットを決定します。また、オブジェクトを取得している間、ハッシュを使用してオブジェクトバケットを検索します。保存後にオブジェクトを変更すると、オブジェクトのハッシュコードが変更され、Setが正しいオブジェクトを取得できない場合があります。コレクションにオブジェクトを追加した後でもオブジェクトを変更する必要がある場合は、ハッシュ化されたコレクションを使用することはお勧めできません。むしろArraylist
を選択しますが、ArrayList
を使用すると、セットの場合と同様に、目的の生徒をすばやく取得できるという利点が失われることに注意してください。
オブジェクトのSet
メソッドの結果が変更される場合は、equals
を使用しないでください。安定した一意のID番号で学生を識別していて、equals
がそのIDをチェックするだけの場合は、Set
を使用しても問題ありません。
HashSet
はインデックス作成と比較にhashCode
を使用し、hashCode
はequals
を決定するために使用されるフィールドを正確に組み込む必要があることに注意してください。
Set のjavadocは
注:可変オブジェクトをセット要素として使用する場合は、細心の注意を払う必要があります。 オブジェクトがセット内の要素であるときに、オブジェクトの値が等しい比較に影響を与える方法で変更された場合、セットの動作は指定されません。この禁止の特別な場合は、セットがそれ自体を要素として含むことは許可されないということです。
したがって、HashSet
を使用する場合、不変フィールドに基づいてhashCode()
とequals()
を作成すると、この問題は発生しません。たとえば、インスタンスごとに一意のstudentIDを使用します。