Java のリストには繰り返しの要素 (ハッシュ コードと等号) が含まれる場合があるため、リストの重複を排除するには 2 つの方法があります。
オプション 1: HashSet を通じて実装できます。コードは次のとおりです。
次のようにコードをコピーします。
クラス学生{
プライベート文字列ID;
プライベート文字列名。
public Student(文字列 ID, 文字列名) {
素晴らしい();
this.id = ID;
this.name = 名前;
}
@オーバーライド
public String toString() {
return "学生 [id=" + id + ", name=" + name + "]";
}
@オーバーライド
public int hashCode() {
最終 int プライム = 31;
int 結果 = 1;
結果 = プライム * 結果 + ((id == null) ? 0 : id.hashCode());
結果 = プライム * 結果 + ((name == null) ? 0 : name.hashCode());
結果を返します。
}
@オーバーライド
public booleanquals(Object obj) {
if (this == obj) {
true を返します。
}
if (obj == null) {
false を返します。
}
if (getClass() != obj.getClass()) {
false を返します。
}
学生その他 = (学生) obj;
if (id == null) {
if (other.id != null) {
false を返します。
}
else if (!id.equals(other.id)) {
false を返します。
}
if (名前 == null) {
if (other.name != null) {
false を返します。
}
else if (!name.equals(other.name)) {
false を返します。
}
true を返します。
}
}
2 つのメソッド、hashCode とquals を実装する必要があります。特定のオペレーション コードを次のように実装する必要がある理由をすぐに説明します。
次のようにコードをコピーします。
プライベート静的無効removeListDuplicateObject() {
List<Student> list = new ArrayList<Student>();
for (int i = 0; i < 10; i++) {
Student Student = new Student("id", "name");
list.add(学生);
}
System.out.println(Arrays.toString(list.toArray()));
Set<Student> set = new HashSet<Student>();
set.addAll(リスト);
System.out.println(Arrays.toString(set.toArray()));
list.removeAll(リスト);
set.removeAll(set);
System.out.println(Arrays.toString(list.toArray()));
System.out.println(Arrays.toString(set.toArray()));
}
呼び出しコード:
次のようにコードをコピーします。
public static void main(String[] args) {
RemoveListDuplicateObject();
}
HashSet を使用して重複排除操作を実行する場合、なぜ hashCode メソッドとquals メソッドをオーバーライドする必要があるのでしょうか?
次のように HashSet の追加操作のソース コードを確認してみましょう。
次のようにコードをコピーします。
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
HashMap は操作のために呼び出されます。 HashMap の put 操作を見てみましょう。
次のようにコードをコピーします。
public V put(K キー, V 値) {
if (キー == null)
putForNullKey(値)を返します;
int ハッシュ = ハッシュ(key.hashCode());
int i =indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
オブジェクト k;
if (e.hash == ハッシュ && ((k = e.key) == キー || key.equals(k)) {
VoldValue = e.value;
e.value = 値;
e.recordAccess(this);
oldValue を返します。
}
}
modCount++;
addEntry(ハッシュ、キー、値、i);
null を返します。
}
注意すべき点は次のとおりです。
次のようにコードをコピーします。
if (e.hash == ハッシュ && ((k = e.key) == キー || key.equals(k)) {
...
}
つまり、ハッシュコードは等しい、と等しい(==)です。
複雑さ: 片側をトラバースするだけ、O(n)
オプション 2: リストを直接走査し、contains 操作と add 操作を実装します。 コードは次のとおりです。
次のようにコードをコピーします。
プライベート静的無効removeListDuplicateObjectByList() {
List<Student> list = new ArrayList<Student>();
for (int i = 0; i < 10; i++) {
Student Student = new Student("id", "name");
list.add(学生);
}
System.out.println(Arrays.toString(list.toArray()));
List<Student> listUniq = new ArrayList<Student>();
for (学生 学生 : リスト) {
if (!listUniq.contains(student)) {
listUniq.add(学生);
}
}
System.out.println(Arrays.toString(listUniq.toArray()));
list.removeAll(リスト);
listUniq.removeAll(listUniq);
System.out.println(Arrays.toString(list.toArray()));
System.out.println(Arrays.toString(listUniq.toArray()));
}
その他は上記と同じです。
複雑:
トラバース中に、contains メソッドが同時に呼び出され、次のようにソース コードが表示されます。
次のようにコードをコピーします。
public boolean contains(Object o) {
戻りindexOf(o) >= 0;
}
public int indexOf(オブジェクトo) {
if (o == null) {
for (int i = 0; i < サイズ; i++)
if (要素データ[i]==null)
私を返します。
} それ以外 {
for (int i = 0; i < サイズ; i++)
if (o.equals(elementData[i]))
私を返します。
}
-1 を返します。
}
新しいリストに対して別の走査操作が実行されたことがわかります。つまり、1+2+....+n、複雑さは O(n*n) です。
結論は:
解決策 1 は非常に効率的です。つまり、HashSet を使用して重複排除操作を実行します。