提供されたList
に基づいて順序を維持する既存のComparator
実装がJavaにありますか?
次の方法で使用できるもの:
Comparator<T> cmp = new MyComparator<T>();
List<T> l = new OrderedList<T>(cmp);
l.add(someT);
someT
が挿入され、リスト内の順序がcmp
に従って維持されるようにします。
(@andersojの提案では、もう1つのリクエストで質問を完了しています)
また、要素を削除せずにリストをソートされた順序でトラバースできるようにしたい、つまり:
T min = Const.SMALLEST_T;
for (T e: l) {
assertTrue(cmp.compare(min, e) >= 0);
min = e;
}
合格する必要があります。
すべての提案を歓迎します(Collections.sort
順不同の完全なリストでは)、しかし、私はJava.*
または最終的にorg.Apache.*
現在、新しいライブラリを導入するのは難しいため。
注:(UPDATE4)この種類のリストを実装すると、パフォーマンスが不十分になることに気付きました。 2つの一般的なアプローチがあります。
いいえ1. CPUキャッシュミスに問題があります。いいえ2.配列内の要素のシフトに問題があります。
UPDATE2:TreeSet
は、提供されたコンパレータ(MyComparator
)が等しいかどうかをチェックし、それに基づいて、要素が等しいと見なして除外します。 「一意性」フィルタリングではなく、順序付けのためだけにそのコンパレータが必要です(自然な順序付けによる要素が等しくないため)
UPDATE3:PriorityQueue
はList
として機能しません私が必要とするのは、要素を「ソート」された順序でトラバースする方法がないためです。要素をソートされた順序で取得するには、コレクションから削除する必要があります。
更新:
新しい要件への対応。私には2つの可能性があります。
PriorityQueue
のJavaDocが言うことを実行します。
このクラスとその反復子は、CollectionおよびIteratorインターフェースのすべてのオプションメソッドを実装します。メソッド
iterator()
で提供されるイテレータは、特定の順序で優先度キューの要素をトラバースすることが保証されていません。順序付けられた走査が必要な場合は、Arrays.sort(pq.toArray())
の使用を検討してください。
私はこれがあなたの要件を与えられた最高のパフォーマンスをもたらすと思います。これが受け入れられない場合は、達成しようとしていることをよりよく説明する必要があります。
Listを作成します。このリストは、新しい要素の追加時に自動的にソートされます。これは本当に大変です...リンク構造を使用すると、効率的な挿入ソートを実行できますが、局所性は悪いです。配列支援構造を使用した場合、挿入ソートは面倒ですが、トラバーサルの方が優れています。反復/走査が頻繁でない場合は、リストのコンテンツを並べ替えずに保持し、オンデマンドでのみ並べ替えることができます。
私が提案したようにPriorityQueueの使用を検討してください。順番に反復する必要がある場合は、ラッパー反復子を作成してください:
_class PqIter implements Iterator<T>
{
final PriorityQueue<T> pq;
public PqIter(PriorityQueue <T> source)
{
pq = new PriorityQueue(source);
}
@Override
public boolean hasNext()
{
return pq.peek() != null
}
@Override
public T next()
{ return pq.poll(); }
@Override
public void remove()
{ throw new UnsupportedOperationException(""); }
}
_
Guavaの TreeMultiSet
を使用します。次のコードをInteger
でテストしましたが、正しく機能しているようです。
_import com.google.common.collect.TreeMultiset;
public class TreeMultiSetTest {
public static void main(String[] args) {
TreeMultiset<Integer> ts = TreeMultiset.create();
ts.add(1); ts.add(0); ts.add(2);
ts.add(-1); ts.add(5); ts.add(2);
for (Integer i : ts) {
System.out.println(i);
}
}
}
_
以下は、SortedSet
を使用するときに発生していた一意性/フィルタリングの問題に対処しています。イテレータも必要なので、これは機能しません。
本当に必要なものが順序付けられたlistのようなものである場合、 PriorityQueue
を使用できます。
_Comparator<T> cmp = new MyComparator<T>();
PriorityQueue<T> pq = new PriorityQueue<T>(cmp);
pq.add(someT);
_
APIドキュメントがさまざまな操作の時間プロパティについて述べていることに注意してください。
実装メモ:この実装は、エンキューおよびデキューのメソッド(
offer
、poll
、remove()
およびadd
);remove(Object)
およびcontains(Object)
メソッドの線形時間。および定数検索メソッドの時間(peek
、element
、およびsize
)。
また、PriorityQueue
によって生成されたイテレータは、期待どおりに動作しないことにも注意してください。
メソッド
iterator()
で提供されるIterator
は、特定の順序で優先度キューの要素をトラバースすることが保証されていません。順序付けられた走査が必要な場合は、Arrays.sort(pq.toArray())
の使用を検討してください。
Guavaが MinMaxPriorityQueue
を提供していることに気づきました。この実装は、JDKのPriorityQueue
で提供されるリンクされたフォームではなく、配列でサポートされているため、タイミングの動作が異なる可能性があります。パフォーマンスに敏感な何かをしている場合は、確認することをお勧めします。ノートは、わずかに異なる(線形および対数)big-O時間を示しますが、それらすべての時間も制限されているはずです。
順序付けを維持するList
実装自体はありませんが、探しているのは SortedSet
の実装です。 TreeSet
が最も一般的です。もう1つの実装であるConcurrentSkipListSet
は、より具体的な用途向けです。 SortedSet
は順序付けを提供しますが、List
のように重複したエントリは許可しないことに注意してください。
参照:
PriorityQueue
イテレータは順序付けされていませんおそらく TreeSet を使用する必要があります。
要素は、使用されるコンストラクターに応じて、自然な順序を使用して、またはセットの作成時に提供されるコンパレーターによって順序付けられます。
例:
Comparator<T> cmp = new MyComparator<T>();
TreeSet<T> t = new TreeSet<T>(cmp);
l.add(someT);
これはsetなので、重複したエントリは許可されないことに注意してください。これは、特定のユースケースで機能する場合と機能しない場合があります。