には、どうするのがベストなの除去を重複を配列をJava?
-
21-08-2019 - |
質問
していま格納するオブジェクトの配列が必要な重複を取り除/ろ過した。思っequals&hachCodeオブジェクトの要素があり、貼付けてセット---がきっかけになるかもしれないと思う少なくとも投票stackoverflowがきていることを確認して下さいたという、かなる方法その他のAPI?
解決
このアプローチをオーバーライド hashCode()
や equals()
用いることを明確にする Set
.
うものではあらかじめ明確に、その他のメーカーが重複しない特性が求められている。
別の理由の-選択の実施お客様のニーズにあった最高の現在:
られないときには、いくつかの変更コードの変更を実施する。
他のヒント
このウェブ
ここでは二つの方法を許可する重複を除去するArrayList.removeDuplicateな秩序を維持しremoveDuplicateWithOrderを維持し、一部の性能オーバーヘッド。
のremoveDuplicate方法
/** List order not maintained **/ public static void removeDuplicate(ArrayList arlList) { HashSet h = new HashSet(arlList); arlList.clear(); arlList.addAll(h); }
のremoveDuplicateWithOrder方法
/** List order maintained **/ public static void removeDuplicateWithOrder(ArrayList arlList) { Set set = new HashSet(); List newList = new ArrayList(); for (Iterator iter = arlList.iterator(); iter.hasNext();) { Object element = iter.next(); if (set.add(element)) newList.add(element); } arlList.clear(); arlList.addAll(newList); }
equals
とhashCode
をオーバーライドし、セットを作成することは、あまりにも私が最初に考えました。それはあなたの継承階層にとにかくこれらの方法のうちのいくつかオーバーライドされたバージョンを持っているようにするとよいでしょう。
私は
... はLinkedHashSet
を使用している場合、あなたもユニークな要素の順序を保存します。のことを考えます 基本的には、ランダムアクセスのためのLinkedHashSet<T>
インタフェースをサポートList<T>
の実装をしたいです。したがって、これは何が必要です。
public class LinkedHashSetList<T> extends LinkedHashSet<T> implements List<T> {
// Implementations for List<T> methods here
...
}
List<T>
メソッドの実装は、基礎となるLinkedHashSet<T>
にアクセスして操作します。あなたはどちらかのいずれかを選択するか、ユーザにより設定可能にすることができますトリックは、1つの選択肢となり異なるインデックスで例外または再追加アイテムを投げる方法を(追加List<T>
を経由して、重複を追加しようとしたとき、このクラスが正しく動作することですクラスの)。
リスト distinctList
録音の要素を、最初の時間 iterator
偶然がとても早いことが気に入っていを返しますdistinctListとしてリストを除去すべての重複を
private List removeDups(List list) {
Set tempSet = new HashSet();
List distinctList = new ArrayList();
for(Iterator it = list.iterator(); it.hasNext();) {
Object next = it.next();
if(tempSet.add(next)) {
distinctList.add(next);
}
}
return distinctList;
}
私はコメントでジェイソンによって作られたポイントを改めて表明したいと思います:
なぜ、全くその時点で自分自身を置く?
全く複製を保持していなければならないデータ構造の配列を使用なぜですか?
(要素が同様に自然の秩序を持っている場合)要素を保持するために、すべての回でSet
またはSortedSet
を使用してください。あなたが挿入順序を保持する必要がある場合、それが指摘されているとして、あなたはLinkedHashSet
を使用することができます。
ポストプロセスいくつかのデータ構造を持つことは、多くの場合、あなたがそもそも違うものを選びだしたはずのヒントです。
もちろん、オリジナルのポストは質問を頼む、「どのようにあなたが最初の場所で(つまり、重複エントリが含まれている場合があります)、その配列を取得するのですか?」
あなたは他の目的のために(重複を含む)の配列が必要ですか、単に最初からセットを使用することができます?
あなたは、各値の出現数を知る必要がある場合、代わりに、あなたはカウントを追跡するためにMap<CustomObject, Integer>
を使用することができます。また、 MultimapはクラスのGoogleのコレクションの定義は、使用のものであってもよいです。
Set
は間違いなくあなたの最善の策です。 (新しいものを作成せず)のアレイから物事を削除する唯一の方法は、それらをnullにあり、その後、後でヌル・チェックの多くで終わるます。
一般的なプログラミングの標準からいえば、あなたは常に二重のソースとターゲットを比較し、その後、コレクションを列挙することができます。
そして、あなたの内側の列挙は、常にソースの後に一つのエントリを開始した場合、それはかなり効率的です(擬似コードフォローする)
foreach ( array as source )
{
// keep track where we are in the array
place++;
// loop the array starting at the entry AFTER the current one we are comparing to
for ( i=place+1; i < max(array); i++ )
{
if ( source === array[place] )
{
destroy(array[i]);
}
}
}
あなたは間違いなくブレークを追加することができます。文の後に破壊するが、その後あなただけの最初の重複を発見し、それはあなたが持っているだろうすべてをだならば、それは素敵な小さな最適化となります。