Apache Commons Collections Bag

1. Introduction

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

2. Maven Dependency

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

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

3. Bags vs Collections

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

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

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

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

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<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:

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

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

4. Bag Implementations

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

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:

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

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

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:

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:

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

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

4.3. SynchronizedSortedBag

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

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

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.

5. Conclusion

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

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

Related posts:

Spring Data JPA Delete and Relationships
The Spring @Controller and @RestController Annotations
A Guide to the Java LinkedList
Java Program to Check if a Given Set of Three Points Lie on a Single Line or Not
Java Program to Implement the Binary Counting Method to Generate Subsets of a Set
Collection trong java
How to Find an Element in a List with Java
Java Program to Implement Segment Tree
Spring Data MongoDB – Indexes, Annotations and Converters
Spring Boot - Creating Docker Image
Java Program to Implement Brent Cycle Algorithm
Format ZonedDateTime to String
Java Program to Implement Shunting Yard Algorithm
Guide to UUID in Java
Java Program to find the maximum subarray sum using Binary Search approach
Spring Boot - Apache Kafka
Serialize Only Fields that meet a Custom Criteria with Jackson
Java Program to Implement Depth-limited Search
Java Program to Represent Graph Using Incidence Matrix
Vector trong Java
The Registration API becomes RESTful
Java Program to Find the Vertex Connectivity of a Graph
Java Program to Test Using DFS Whether a Directed Graph is Strongly Connected or Not
Java Program to Implement Quick Sort Using Randomization
Netflix Archaius with Various Database Configurations
Apache Commons Collections SetUtils
Getting Started with Forms in Spring MVC
Java Program to add two large numbers using Linked List
Spring Boot - Tracing Micro Service Logs
HTTP Authentification and CGI/Servlet
Java Program to Check the Connectivity of Graph Using DFS
Java Program to Find Nearest Neighbor for Dynamic Data Set