web-dev-qa-db-ja.com

スタックを実装するためのArrayDequeとArrayList

ArrayDequeのドキュメントはこう言っています:

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

ArrayDequeをスタックとして使用する場合とArrayListを使用する場合の違いについては触れられていません。次のように、ArrayListをスタックとして使用できます。

_list.add(object);                      // Push
object = list.remove(list.size() - 1); // pop
_

この方法でのみArrayListを使用すると、ArrayDequeよりもパフォーマンスが低下することがわかりました。この違いの原因は何ですか?確かに、それはsize()の呼び出しだけではありませんか?内部的には、ArrayListArrayDequeは、必要に応じてより大きな配列に置き換えられる_Object[]_を使用して実装されるため、パフォーマンスはほぼ同じですか?

27
Paul Boddington

両方の実装の主な違いは、サイズ変更戦略です

  • ArrayListのサイズがoldCapacity + (oldCapacity >> 1)の新しいサイズに変更され、増分が約50%になります。デフォルトの容量は10で、サイズ変更後の容量は15,22,33,49,73,109,163,244,366 ...になります。

  • ArrayDequeは常に2の累乗にサイズ変更されます。サイズ変更時に、容量は2倍になります。デフォルトの16から始めて、サイズ変更後の再スケジュール能力は32、64、128、256、...

そのため、ArrayDequeはサイズ変更操作がはるかに少なくて容量が大きくなり、アレイのコピーのためにコストがかかります。つまりデフォルトサイズのArrayListに256を格納するには、9回のサイズ変更呼び出しが必要ですが、ArrayDequeは4つしか必要ありません。配列のコピーは高速かもしれませんが、GCがメモリコピーに加えて新しいデータセット用にいくつかの領域を解放する必要がある場合もあります。コスト(ArrayDequeは、2の累乗に対応しているため、パフォーマンスも向上する可能性があります)。

どちらのデータ構造も、headtail(ArrayDequeue)への直接アクセスによるプッシュおよびポップの場合、それぞれO(1))の複雑さがあります。追加および削除(最後)size(ArrayList)

18
Gerald Mücke