Apache Commons Collections Bag – 阿帕奇共享资源收集袋

最后修改: 2017年 9月 28日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

In this quick article, we’ll focus on how to use the Apache’s Bag collection.

在这篇简短的文章中,我们将重点讨论如何使用Apache的Bag集合。

2. Maven Dependency

2.Maven的依赖性

Before we start, we need to import the latest dependencies from Maven Central:

在开始之前,我们需要从Maven Central导入最新的依赖项。

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.1</version>
</dependency>

3. Bags vs Collections

3.箱包与收藏

Simply put, Bag is a collection that allows storing multiple items along with their repetition count:

简单地说,Bag是一个允许存储多个项目及其重复次数的集合。

public void whenAdded_thenCountIsKept() {
    Bag<Integer> bag = new HashBag<>(
      Arrays.asList(1, 2, 3, 3, 3, 1, 4));
        
    assertThat(2, equalTo(bag.getCount(1)));
}

3.1. Violations of the Collection Contract

3.1.违反收集合同的行为

While reading Bag‘s API documentation, we may notice that some methods are marked as violating the standard Java’s Collection contract.

在阅读Bag的API文档时,我们可能会注意到一些方法被标记为违反了标准的Java的集合契约。

For example, when we use an add() API from a Java collection, we receive true even if the item is already in the collection:

例如,当我们从一个Java集合中使用add() API时,我们会收到true,即使该项目已经在集合中。

Collection<Integer> collection = new ArrayList<>();
collection.add(1);
assertThat(collection.add(1), is(true));

The same API from a Bag implementation will return a false when we add an element which is already available in the collection:

当我们添加一个在集合中已经存在的元素时,来自Bag实现的相同API将返回false

Bag<Integer> bag = new HashBag<>();
bag.add(1);
 
assertThat(bag.add(1), is(not(true)));

To resolve these issues, Apache Collections’ library provides a decorator called the CollectionBag. We can use this to make our bag collections compliant with the Java Collection contract:

为了解决这些问题,Apache Collections库提供了一个名为CollectionBag.的装饰器,我们可以使用它来使我们的袋子集合符合JavaCollection契约。

public void whenBagAddAPILikeCollectionAPI_thenTrue() {
    Bag<Integer> bag = CollectionBag.collectionBag(new HashBag<>());
    bag.add(1);

    assertThat(bag.add(1), is((true)));
}

4. Bag Implementations

4.袋子的实施

Let’s now explore the various implementations of the Bag interface – within Apache’s collections library.

现在让我们来探索Bag接口的各种实现–在Apache的集合库中。

4.1. HashBag

4.1.HashBag

We can add an element and instruct the API on the number of copies this element should have in our bag collection:

我们可以添加一个元素,并指示API这个元素在我们的袋子集合中应该有多少个副本。

public void givenAdd_whenCountOfElementsDefined_thenCountAreAdded() {
    Bag<Integer> bag = new HashBag<>();
	
    bag.add(1, 5); // adding 1 five times
 
    assertThat(5, equalTo(bag.getCount(1)));
}

We can also delete a specific number of copies or every instance of an element from our bag:

我们还可以从我们的包中删除特定数量的副本或某个元素的每个实例。

public void givenMultipleCopies_whenRemove_allAreRemoved() {
    Bag<Integer> 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

4.2. TreeBag

The TreeBag implementation works like any other tree, additionally maintaining Bag semantics.

TreeBag的实现像其他树一样工作,另外还保持Bag的语义。

We can naturally sort an array of integers with a TreeBag and then query the number of instances each individual element has within the collection:

我们可以用TreeBag对一个整数数组进行自然排序,然后查询每个元素在集合中的实例数量。

public void givenTree_whenDuplicateElementsAdded_thenSort() {
    TreeBag<Integer> 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));
}

The TreeBag implements a SortedBag interface, all implementations of this interface can use the decorator CollectionSortedBag to comply with the Java Collections contract:

TreeBag实现了一个SortedBag接口,这个接口的所有实现都可以使用装饰器CollectionSortedBag来遵守Java集合合同。

public void whenTreeAddAPILikeCollectionAPI_thenTrue() {
    SortedBag<Integer> bag 
      = CollectionSortedBag.collectionSortedBag(new TreeBag<>());

    bag.add(1);
 
    assertThat(bag.add(1), is((true)));
}

4.3. SynchronizedSortedBag

4.3.SynchronizedSortedBag

Another widely used implementation of Bag is the SynchronizedSortedBag. Precisely, this is a synchronized decorator of a SortedBag implementation.

另一个广泛使用的Bag的实现是SynchronizedSortedBag。准确地说,这是一个SortedBag实现的同步装饰器。

We can use this decorator with our TreeBag (an implementation of SortedBag) from the previous section to synchronize access to our bag:

我们可以将这个装饰器与我们的TreeBagSortedBag的一个实现)一起使用,以同步访问我们的包。

public void givenSortedBag_whenDuplicateElementsAdded_thenSort() {
    SynchronizedSortedBag<Integer> 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));
}

We can use a combination of APIs – Collections.synchronizedSortedMap() and TreeMap – to simulate what we did here with SynchronizedSortedBag.

我们可以使用API的组合–Collections.synchronizedSortedMap() TreeMap–来模拟我们在这里用SynchronizedSortedBag做的事情。

5. Conclusion

5.结论

In this short tutorial, we’ve learned about the Bag interface and its various implementations.

在这个简短的教程中,我们已经了解了Bag接口和它的各种实现。

As always, the code for this article can be found over on GitHub.

像往常一样,本文的代码可以在GitHub上找到over

Next »

Apache Commons Collections SetUtils