web-dev-qa-db-ja.com

重複しないリストの実装はありますか?

SortedSet について知っていますが、私の場合は、Listではなく、Setを実装するものが必要です。 APIや他の場所に実装はありますか?

自分で実装するのは難しいことではないはずですが、最初にここにいる人に聞いてみませんか?

81
Yuval

標準ライブラリには、これを行うためのJavaコレクションはありません。 LinkedHashSet<E>Listと同様に順序を保持します。そのため、Listとして使用するときにListでセットをラップすると、必要なセマンティクスを取得します。

または、 Commons Collections (またはcommons-collections4(汎用バージョンの場合)にはListがあり、これは既に必要なことを行います。 SetUniqueList / SetUniqueList<E>

86
Calum

これが私がやったことであり、動作します。

私がArrayListを持っていると仮定すると、私が最初にしたことは新しいLinkedHashMapを作成したことです。

LinkedHashSet<E> hashSet = new LinkedHashSet<E>()

次に、新しい要素をLinkedHashSetに追加しようとします。 addメソッドはLinkedHasSetを変更せず、新しい要素が重複している場合はfalseを返します。したがって、これはArrayListに追加する前にテストできる条件になります。

if (hashSet.add(E)) arrayList.add(E);

これは、重複が配列リストに追加されるのを防ぐためのシンプルでエレガントな方法です。必要に応じて、それをカプセル化し、ArrayListを拡張するクラスでaddメソッドをオーバーライドできます。要素をループしてaddメソッドを呼び出すことで、addAllを処理することを忘れないでください。

12
user3570018

だから私は最終的にやったことです。これが他の人の助けになることを願っています。

class NoDuplicatesList<E> extends LinkedList<E> {
    @Override
    public boolean add(E e) {
        if (this.contains(e)) {
            return false;
        }
        else {
            return super.add(e);
        }
    }

    @Override
    public boolean addAll(Collection<? extends E> collection) {
        Collection<E> copy = new LinkedList<E>(collection);
        copy.removeAll(this);
        return super.addAll(copy);
    }

    @Override
    public boolean addAll(int index, Collection<? extends E> collection) {
        Collection<E> copy = new LinkedList<E>(collection);
        copy.removeAll(this);
        return super.addAll(index, copy);
    }

    @Override
    public void add(int index, E element) {
        if (this.contains(element)) {
            return;
        }
        else {
            super.add(index, element);
        }
    }
}   
10
Yuval

Dhillerの答えを真剣に検討してください:

  1. オブジェクトを重複のないリストに追加することを心配する代わりに、オブジェクトをセット(任意の実装)に追加します。これにより、本質的に重複が除外されます。
  2. Listを必要とするメソッドを呼び出す必要がある場合は、new ArrayList(set)(またはnew LinkedList(set)など)でラップします。

NoDuplicatesListを使用して投稿したソリューションには、主にcontains()メソッドに関する問題があり、さらに、クラスがaddAll() 方法。

4
matt b

セットをリストでカプセル化しないのはなぜですか?

new ArrayList( new LinkedHashSet() )

これは、コレクションの本当のマスターである誰かのために他の実装を残します;-)

4
Daniel Hiller

私はそのようなものが必要だったので、commonsコレクションに行き、SetUniqueListを使用しましたが、パフォーマンステストを実行したときに、Setを使用して配列を取得する場合の場合と比較して最適化されていないようですSet.toArray()メソッドでは、SetUniqueTestが他の実装と比較して100,000文字列を埋めてから走査するのに20:1の時間がかかりました。これは大きな違いであるため、パフォーマンスを心配する場合は、SetおよびSetUniqueListのロジックが本当に必要な場合を除き、SetUniqueListを使用する代わりに配列を取得し、他のソリューションを確認する必要があります...

テストコードのメインメソッド:

public static void main(String [] args){

SetUniqueList pq = SetUniqueList.decorate(new ArrayList());
Set s = new TreeSet();

long t1 = 0L;
long t2 = 0L;
String t;


t1 = System.nanoTime();
for (int i = 0; i < 200000; i++) {
    pq.add("a" + Math.random());
}
while (!pq.isEmpty()) {
    t = (String) pq.remove(0);
}
t1 = System.nanoTime() - t1;

t2 = System.nanoTime();
for (int i = 0; i < 200000; i++) {
    s.add("a" + Math.random());
}

s.clear();
String[] d = (String[]) s.toArray(new String[0]);
s.clear();
for (int i = 0; i < d.length; i++) {
    t = d[i];

}
t2 = System.nanoTime() - t2;

System.out.println((double)t1/1000/1000/1000); //seconds
System.out.println((double)t2/1000/1000/1000); //seconds
System.out.println(((double) t1) / t2);        //comparing results

}

よろしくMohammed Sleem http://abusleem.net/blog

3
Mohammed Sleem

注:subListの実装は考慮されません。

import Java.util.ArrayList;
import Java.util.Collection;
import Java.util.HashSet;
import Java.util.Set;

public class UniqueList<T> extends ArrayList<T> {

    private static final long serialVersionUID = 1L;

    /** Unique elements SET */
    private final Set<T> set=new HashSet();

    /** Used by addAll methods */
    private Collection<T> addUnique(Collection<? extends T> col) {
        Collection<T> unique=new ArrayList();
        for(T e: col){
            if (set.add(e)) unique.add(e);
        }
        return unique;
    }

    @Override
    public boolean add(T e) {
        return set.add(e) ? super.add(e) : false;
    }

    @Override
    public boolean addAll(Collection<? extends T> col) {
        return super.addAll(addUnique(col));
    }

    @Override
    public void add(int index, T e) {
        if (set.add(e)) super.add(index, e);
    }

    @Override
    public boolean addAll(int index, Collection<? extends T> col) {
        return super.addAll(index, addUnique(col));
    }

}
1
marcolopes

コレクションインターフェイスのドキュメント は次のとおりです。

セット—重複する要素を含むことができないコレクション。
List —順序付けられたコレクション(シーケンスとも呼ばれます)。リストには重複した要素を含めることができます。

したがって、重複が必要ない場合は、おそらくリストを使用しないでください。

0
Hauch