Javaでの高速なqueue
実装を探しています。 LinkedList
はQueue
インターフェースを実装しているようですが、それはLinkedList
と同じくらい高速ですよね?特にadd
の場合に高速になるキューを作成する方法はありますか(必要なのはpoll
、add
、empty
のみです)。将来的には、PriorityQueue
も必要になるかもしれませんが、まだです。
LinkedListがQueueインターフェースを実装しているようですが、LinkedListと同じくらい高速になりますよね?
ソースコードに注目すると、LinkedListは、Queue.add、Queue.poll、およびQueue.peek操作の場合はO(1)です。
私はそれが十分に速いことを願っています。
複数のスレッドがキューにアクセスする場合は、 ArrayBlockingQueue
の使用を検討してください。それ以外の場合は、 ArrayDeque
を見てください。 ArrayDeque
APIから:
このクラスは、スタックとして使用する場合はStackよりも高速であり、キューとして使用する場合はLinkedListよりも高速である可能性があります。
具体的には、配列ベースのキューの実装により、既存の配列に十分な容量がある場合に基になる配列のサイズを変更する必要性が減り、キューへの追加が通常LinkedList
よりも速くなります。 ArrayBlockingQueue
は制限付きの実装ですが、ArrayDeque
は必要に応じてサイズが変更されることに注意してください。
反対に、LinkedList
は通常、はるかにコンパクトな表現を提供します。特に、キューが大幅に拡大および縮小する場合はそうです。たとえば、ArrayDeque
に10,000,000個の要素を追加してから、9,999,999個の要素を削除した場合、基になる配列の長さは10,000,000のままですが、LinkedList
ではこの問題は発生しません。
実際には、非ブロッキングキューへのシングルスレッドアクセスの場合、私はLinkedList
を好む傾向があります。パフォーマンスの違いはごくわずかで、とにかく違いに気付かないと思います。
リンクリストのパフォーマンスが本当に問題である場合、代替手段は、配列に「循環キュー」を実装することです。つまり、エントリが追加および削除されるときに開始点と終了点が移動するキューです。よろしければ詳細をお知らせします。コレクションのライブラリがない言語を使用していたときは、リンクリストよりも記述が簡単で高速だったため、常にキューを実装していました。しかし、組み込みのコレクションを使用すると、特別な場合のために自分のコレクションを作成してデバッグする作業は、99%の確率で問題を起こす価値がありません。既に作成されている場合は、別の方法で作成できるという事実があります。 Javaのように書き直すことは、ほとんど関係のない事実です。パフォーマンスの向上は小さすぎて問題に値しない可能性があります。既存のコレクションをサブタイプ化して、特別な動作を実現します。時々必要ですが、最後に一から書いた時のことを考えるのは大変です。
GapList
を紹介する http://Java.dzone.com/articles/gaplist-%E2%80%93-lightning-fast-list をご覧ください。この新しいリストの実装は、ArrayList
とLinkedList
の両方の長所を組み合わせたものです。
したがって、Deque
インターフェースを実装しますが、上記のArrayDeque
のように事前にサイズ設定することもできます。さらに、List
インターフェースのすべての可能性を無料で入手できます。
「C/C++のような」態度と固定サイズの非常に単純な回転キューの実装から始めます。
class SimpleQueue<E>
{
int index = 0;
int head = 0;
int size = 100;
int counter = 0;
E[] data ;
@SuppressWarnings("unchecked")
SimpleQueue()
{
data = (E[]) new Object[size];
}
public void add(E e)
{
data[index]=e;
index=(index+1)%size;
counter++;
}
public E poll()
{
E value = data[head];
head=(head+1)%size;
counter--;
return value;
}
public boolean empty()
{ return counter==0; }
//Test
public static void main(String[] args)
{
SimpleQueue<Integer> s = new SimpleQueue<Integer>();
System.out.println(s.empty());
for(int i=0; i< 10; i++)
s.add(i);
System.out.println(s.empty());
for(int i=0; i<10; i++)
System.out.print(s.poll()+",");
System.out.println("\n"+s.empty());
}
}
そしてそれを改善します。