web-dev-qa-db-ja.com

Javaの高速キュー

Javaでの高速なqueue実装を探しています。 LinkedListQueueインターフェースを実装しているようですが、それはLinkedListと同じくらい高速ですよね?特にaddの場合に高速になるキューを作成する方法はありますか(必要なのはpolladdemptyのみです)。将来的には、PriorityQueueも必要になるかもしれませんが、まだです。

21
Eqbal

LinkedListがQueueインターフェースを実装しているようですが、LinkedListと同じくらい高速になりますよね?

ソースコードに注目すると、LinkedListは、Queue.add、Queue.poll、およびQueue.peek操作の場合はO(1)です。

私はそれが十分に速いことを願っています。

28
Noel Ang

複数のスレッドがキューにアクセスする場合は、 ArrayBlockingQueue の使用を検討してください。それ以外の場合は、 ArrayDeque を見てください。 ArrayDeque AP​​Iから:

このクラスは、スタックとして使用する場合はStackよりも高速であり、キューとして使用する場合はLinkedListよりも高速である可能性があります。

具体的には、配列ベースのキューの実装により、既存の配列に十分な容量がある場合に基になる配列のサイズを変更する必要性が減り、キューへの追加が通常LinkedListよりも速くなります。 ArrayBlockingQueueは制限付きの実装ですが、ArrayDequeは必要に応じてサイズが変更されることに注意してください。

反対に、LinkedListは通常、はるかにコンパクトな表現を提供します。特に、キューが大幅に拡大および縮小する場合はそうです。たとえば、ArrayDequeに10,000,000個の要素を追加してから、9,999,999個の要素を削除した場合、基になる配列の長さは10,000,000のままですが、LinkedListではこの問題は発生しません。

実際には、非ブロッキングキューへのシングルスレッドアクセスの場合、私はLinkedListを好む傾向があります。パフォーマンスの違いはごくわずかで、とにかく違いに気付かないと思います。

31
Adamski

リンクリストのパフォーマンスが本当に問題である場合、代替手段は、配列に「循環キュー」を実装することです。つまり、エントリが追加および削除されるときに開始点と終了点が移動するキューです。よろしければ詳細をお知らせします。コレクションのライブラリがない言語を使用していたときは、リンクリストよりも記述が簡単で高速だったため、常にキューを実装していました。しかし、組み込みのコレクションを使用すると、特別な場合のために自分のコレクションを作成してデバッグする作業は、99%の確率で問題を起こす価値がありません。既に作成されている場合は、別の方法で作成できるという事実があります。 Javaのように書き直すことは、ほとんど関係のない事実です。パフォーマンスの向上は小さすぎて問題に値しない可能性があります。既存のコレクションをサブタイプ化して、特別な動作を実現します。時々必要ですが、最後に一から書いた時のことを考えるのは大変です。

6
Jay

GapListを紹介する http://Java.dzone.com/articles/gaplist-%E2%80%93-lightning-fast-list をご覧ください。この新しいリストの実装は、ArrayListLinkedListの両方の長所を組み合わせたものです。

したがって、Dequeインターフェースを実装しますが、上記のArrayDequeのように事前にサイズ設定することもできます。さらに、Listインターフェースのすべての可能性を無料で入手できます。

4
Thomas Mauch

「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());

}
}

そしてそれを改善します。

1
Jan Cajthaml