Apache Commonsコレクションバッグ
1. 前書き
この簡単な記事では、ApacheのBagコレクションの使用方法に焦点を当てます。
参考文献:
2. メーベン依存
開始する前に、Maven Centralから最新の依存関係をインポートする必要があります。
org.apache.commons
commons-collections4
4.1
3. バッグvsコレクション
簡単に言うと、Bagは、複数のアイテムとその繰り返し数を格納できるコレクションです。
public void whenAdded_thenCountIsKept() {
Bag bag = new HashBag<>(
Arrays.asList(1, 2, 3, 3, 3, 1, 4));
assertThat(2, equalTo(bag.getCount(1)));
}
3.1. Collection契約の違反
BagのAPIドキュメントを読んでいると、一部のメソッドが標準のJavaのコレクションコントラクトに違反しているとマークされていることに気付く場合があります。
たとえば、Javaコレクションからadd() APIを使用すると、アイテムがすでにコレクションに含まれている場合でも、trueを受け取ります。
Collection collection = new ArrayList<>();
collection.add(1);
assertThat(collection.add(1), is(true));
コレクションですでに使用可能な要素を追加すると、Bag実装の同じAPIがfalseを返します。
Bag bag = new HashBag<>();
bag.add(1);
assertThat(bag.add(1), is(not(true)));
これらの問題を解決するために、Apache CollectionsのライブラリはCollectionBag.と呼ばれるデコレータを提供します。これを使用して、バッグコレクションをJavaCollectionコントラクトに準拠させることができます。
public void whenBagAddAPILikeCollectionAPI_thenTrue() {
Bag bag = CollectionBag.collectionBag(new HashBag<>());
bag.add(1);
assertThat(bag.add(1), is((true)));
}
4. バッグの実装
次に、Apacheのコレクションライブラリ内のBagインターフェイスのさまざまな実装について見ていきましょう。
4.1. HashBag
要素を追加し、この要素をバッグコレクションに含める必要があるコピーの数をAPIに指示できます。
public void givenAdd_whenCountOfElementsDefined_thenCountAreAdded() {
Bag bag = new HashBag<>();
bag.add(1, 5); // adding 1 five times
assertThat(5, equalTo(bag.getCount(1)));
}
バッグから特定の数のコピーまたは要素のすべてのインスタンスを削除することもできます。
public void givenMultipleCopies_whenRemove_allAreRemoved() {
Bag bag = new HashBag<>(
Arrays.asList(1, 2, 3, 3, 3, 1, 4));
bag.remove(3, 1); // remove one element, two still remain
assertThat(2, equalTo(bag.getCount(3)));
bag.remove(1); // remove all
assertThat(0, equalTo(bag.getCount(1)));
}
4.2. TreeBag
TreeBagの実装は他のツリーと同じように機能し、さらにBagのセマンティクスを維持します。
整数の配列をTreeBagで自然に並べ替えてから、個々の要素がコレクション内に持つインスタンスの数をクエリできます。
public void givenTree_whenDuplicateElementsAdded_thenSort() {
TreeBag bag = new TreeBag<>(Arrays.asList(7, 5,
1, 7, 2, 3, 3, 3, 1, 4, 7));
assertThat(bag.first(), equalTo(1));
assertThat(bag.getCount(bag.first()), equalTo(2));
assertThat(bag.last(), equalTo(7));
assertThat(bag.getCount(bag.last()), equalTo(3));
}
TreeBagはSortedBagインターフェースを実装します。このインターフェースのすべての実装は、デコレータCollectionSortedBagを使用してJavaコレクションコントラクトに準拠できます。
public void whenTreeAddAPILikeCollectionAPI_thenTrue() {
SortedBag bag
= CollectionSortedBag.collectionSortedBag(new TreeBag<>());
bag.add(1);
assertThat(bag.add(1), is((true)));
}
4.3. SynchronizedSortedBag
Bagのもう1つの広く使用されている実装は、SynchronizedSortedBagです。 正確には、これはSortedBag実装の同期デコレータです。
このデコレータを前のセクションのTreeBag(SortedBagの実装)とともに使用して、バッグへのアクセスを同期できます。
public void givenSortedBag_whenDuplicateElementsAdded_thenSort() {
SynchronizedSortedBag bag = SynchronizedSortedBag
.synchronizedSortedBag(new TreeBag<>(
Arrays.asList(7, 5, 1, 7, 2, 3, 3, 3, 1, 4, 7)));
assertThat(bag.first(), equalTo(1));
assertThat(bag.getCount(bag.first()), equalTo(2));
assertThat(bag.last(), equalTo(7));
assertThat(bag.getCount(bag.last()), equalTo(3));
}
API –Collections.synchronizedSortedMap()とTreeMap –の組み合わせを使用して、ここでSynchronizedSortedBagを使用して行ったことをシミュレートできます。
5. 結論
この短いチュートリアルでは、Bagインターフェースとそのさまざまな実装について学習しました。
いつものように、この記事のコードはover on GitHubにあります。