1


概要


この記事では、


EvictingQueue



、および

httpsについて説明します。//google.github.io/guava/releases/snapshot/api/docs/com/google/common/collect/MinMaxPriorityQueue.html[MinMaxPriorityQueue]

構文は、Guavaライブラリから作成します。

EvictingQueue

は循環バッファの概念の実装です。

MinMaxPriorityQueue

は、提供された

Comparator.

を使用して、その最小要素と最大要素にアクセスすることを可能にします。


2

EvictingQueue


構築から始めましょう – キューのインスタンスを構築するときは、引数として最大キューサイズを指定する必要があります。


EvictingQueue

に新しいアイテムを追加したいときに、キューがいっぱいになると、自動的に先頭から要素を削除します。

標準キューの動作と比較すると、フルキューに要素を追加してもブロックされずにhead要素が削除され、末尾に新しい項目が追加されます。


EvictingQueue

は、追加専用の方法で要素を挿入するためのリングとして考えることができます。新しい要素を追加したい位置に要素がある場合は、指定された位置にある既存の要素をオーバーライドするだけです。

最大サイズ10の

EvictingQueue

のインスタンスを作成しましょう。次に、それに10個の要素を追加します。

Queue<Integer> evictingQueue = EvictingQueue.create(10);

IntStream.range(0, 10)
  .forEach(evictingQueue::add);

assertThat(evictingQueue)
  .containsExactly(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);

標準のキューを実装している場合、フルキューに新しい項目を追加するとプロデューサがブロックされます。


EvictingQueue

実装ではそうではありません。それに新しい要素を追加すると、そこからheadが削除され、新しい要素がtailに追加されます。

evictingQueue.add(100);

assertThat(evictingQueue)
  .containsExactly(1, 2, 3, 4, 5, 6, 7, 8, 9, 100);

循環バッファとして

EvictingQueue

を使用することで、非常に効率的な並行プログラムを作成できます。


3

MinMaxPriorityQueue



MinMaxPriorityQueue

は、その最小要素と最大要素への一定時間アクセスを提供します。

最小の要素を取得するには、

peekFirst()

メソッドを呼び出す必要があります。最大の要素を取得するために、

peekLast()

メソッドを呼び出すことができます。これらはキューから要素を削除するのではなく、単にそれを取得するだけであることに注意してください。

要素の順序は、このキューのコンストラクターに渡す必要がある

Comparator

によって行われます。

整数型の

value

フィールドを持つ

CustomClass

クラスがあるとしましょう。

class CustomClass {
    private Integer value;

   //standard constructor, getters and setters
}


int

型でコンパレータを使用する

MinMaxPriorityQueue

を作成しましょう。次に、

CustomClass

型の10個のオブジェクトをキューに追加します。

MinMaxPriorityQueue<CustomClass> queue = MinMaxPriorityQueue
  .orderedBy(Comparator.comparing(CustomClass::getValue))
  .maximumSize(10)
  .create();

IntStream
  .iterate(10, i -> i - 1)
  .limit(10)
  .forEach(i -> queue.add(new CustomClass(i)));


MinMaxPriorityQueue

の特性と渡された__Comparatorのために、キューの先頭の要素は1に等しくなり、キューの末尾の要素は10になります。

assertThat(
  queue.peekFirst().getValue()).isEqualTo(1);
assertThat(
  queue.peekLast().getValue()).isEqualTo(10);

キューの容量は10で、要素を10個追加したので、キューはいっぱいです。それに新しい要素を追加すると、キューの最後の要素が削除されます。

value

を-1にして

CustomClass

を追加しましょう。

queue.add(new CustomClass(-1));

そのアクションの後、キュー内の最後の要素は削除され、末尾の新しい項目は9になります。新しいヘッドは-1になります。私たちのキューを構築しました:

assertThat(
  queue.peekFirst().getValue()).isEqualTo(-1);
assertThat(
  queue.peekLast().getValue()).isEqualTo(9);


MinMaxPriorityQueueの仕様によると、キューがいっぱいになった場合の

** 、現在最大の要素より大きい要素を追加すると、その同じ要素が削除され、事実上無視されます。

100という数字を追加して、その操作の後でそのアイテムがキューに入っているかどうかをテストしましょう。

queue.add(new CustomClass(100));
assertThat(queue.peekFirst().getValue())
  .isEqualTo(-1);
assertThat(queue.peekLast().getValue())
  .isEqualTo(9);

ご覧のとおり、キューの最初の要素はまだ-1、最後の要素は9です。したがって、整数を追加しても、キュー内の最大要素よりも大きいので無視されました。


4結論

この記事では、Guavaライブラリーの

EvictingQueue

および

MinMaxPriorityQueue

構成を見ています。

非常に効率的なプログラムを実装するための循環バッファとして

EvictingQueue

を使う方法を見ました。


MinMaxPriorityQueue



Comparator

を組み合わせて使用​​して、最小要素と最大要素に一定時間アクセスできました。

新しい要素を追加すると、すでにキューに入っている要素が上書きされるため、提示された両方のキューの特性を覚えておくことが重要です。これは、新しい要素をフルキューに追加するとプロデューサスレッドがブロックされたり、例外が発生したりする標準的なキュー実装とは反対です。

これらすべての例とコードスニペットの実装はhttps://github.com/eugenp/tutorials/tree/master/guava-collections[GitHubプロジェクト]にあります – これはMavenプロジェクトなので、簡単にできます。そのままインポートして実行します。