リストも実装する挿入順序保存セットはありますか?


84

私はの実装見つけようとしているjava.util.Listjava.util.Set、Javaで同時にします。このクラスで一意の要素(as Set)のみを許可し、それらの順序(like List)を保持する必要があります。JDK 6に存在しますか?

List<T>#add(int, T)特定の位置に挿入できるようにすることが重要です。


それらの挿入順序またはComparator?で定義された順序を保持することを意味しますか?また、Listインターフェースのセマンティクスも必要ですか?

回答:


207

TreeSet要素の順序でソートされます。LinkedHashSet挿入順序を保持します。うまくいけば、それらの1つはあなたが求めていたものです。

任意の場所に挿入できるように指定しましたが、独自に作成する必要があると思います。aHashSet<T>ArrayList<T>;を含むクラスを作成するだけです。アイテムを追加するときは、リストに追加する前に、セットに含まれているかどうかを確認してください。

あるいは、Apacheのcommons-collections4オファーListOrderedSetSetUniqueList、は同様に動作し、指定された要件を満たす必要があります。



12

のような意味LinkedHashSetですか?これにより、エントリの順序は保持されますが、重複は許可されません。

IMHO、それは珍しい要件ですが、重複することなくリストを書くことができます。

class SetList<T> extends ArrayList<T> {
    @Override
    public boolean add(T t) {
        return !super.contains(t) && super.add(t);
    }

    @Override
    public void add(int index, T element) {
        if (!super.contains(element)) super.add(index, element);
    }

    @Override
    public boolean addAll(Collection<? extends T> c) {
        boolean added = false;
        for (T t : c)
            added |= add(t);
        return added;
    }

    @Override
    public boolean addAll(int index, Collection<? extends T> c) {
        boolean added = false;
        for (T t : c)
            if (!super.contains(t)) {
                super.add(index++, t);
                added = true;
            }
        return added;
    }
}

Listインターフェイスは実装されていません。質問に対する私の変更を参照してください
yegor256 2011年

2
stackoverflow.com/a/8185105/253468O(n)挿入の複雑さがないため見栄えが良く、二重ストレージとO(log(n))挿入操作の間で考慮しなければならないトレードオフがあります。
TWiStErRob 2013年

8

あなたは実装できないListSet契約違反せずに一度に。たとえば、Set.hashCode契約を参照してください。

セットのハッシュコードは、セット内の要素のハッシュコードの合計として定義されます。ここで、null要素のハッシュコードはゼロとして定義されます。

一方、ここにの契約がありList.hashCodeます:

リストのハッシュコードは、次の計算の結果として定義されます。

int hashCode = 1;
for (E e : list)
    hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());

したがって、両方の契約が履行されることを保証する単一のクラスを実装することは不可能です。equals実装についても同じ問題。



0

同様の問題があったので、自分で書きました。こちらをご覧くださいIndexedArraySet拡張ArrayListおよび実装Set、それはあなたが必要とするすべての操作をサポートする必要があります。ArrayList次のすべての要素を移動する必要があるため、大きなリストの場合、要素を中央の場所に挿入すると時間がかかる可能性があることに注意してください。私IndexedArraySetはそれを変えません。


0

もう1つのオプション(Listインターフェイス要件を除く)はImmutableSet、挿入順序を保持するGuavaです。彼らのウィキページから:

ソートされたコレクションを除いて、順序は構築時から保持されます。例えば、

ImmutableSet.of("a", "b", "c", "a", "d", "b")

「a」、「b」、「c」、「d」の順序で要素を繰り返し処理します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.