Use Guava Multiset to Count the Occurences of Elements in a List

The Multiset class in Google’s Guava library provides a powerful data structure that extends the capabilities of a traditional Set by allowing multiple occurrences of the same element. This makes Multiset particularly useful for counting elements and solving problems where element frequency matters.

Adding Guava to our Project

If you’re using Maven, add the following dependency to the pom.xml file:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.0.1-jre</version> <!-- Check for the latest version -->
</dependency>

For Gradle, add this to the build.gradle:

implementation 'com.google.guava:guava:31.0.1-jre' // Check for the latest version

Creating a Multiset

To create an empty Multiset, you can use the HashMultiset implementation provided by Guava:

    Multiset<String> multiset = HashMultiset.create();

Create a Multiset with a non-empty list:

        List<String> list = Lists.newArrayList("a", "a", "b");
        Multiset<String> multiset = HashMultiset.create(list);

Check Element Count

We can easily check the count of a specific element in the Multiset:

        List<String> list = Lists.newArrayList("a", "a", "b");
        Multiset<String> multiset = HashMultiset.create(list);

        Assertions.assertEquals(3, multiset.size());
        Assertions.assertEquals(2, multiset.count("a"));
        Assertions.assertEquals(2, multiset.elementSet().size());

Add Elements

We can add elements to a Multiset just like we would with a regular Set, but it also allows for adding multiple occurrences of an element:

        Multiset<String> multiset = HashMultiset.create();
        multiset.add("a");
        multiset.add("a");
        multiset.add("b");
        Assertions.assertEquals(3, multiset.size());
        Assertions.assertEquals(2, multiset.count("a"));
        Assertions.assertEquals(2, multiset.elementSet().size());

Remove Elements

We can remove elements from a Multiset, either reducing their count or completely removing them:

        List<String> list = Lists.newArrayList("a", "a", "b", "b");
        Multiset<String> multiset = HashMultiset.create(list);
        Assertions.assertEquals(4, multiset.size());
        Assertions.assertEquals(2, multiset.count("a"));
        Assertions.assertEquals(2, multiset.elementSet().size());
        multiset.remove("a");
        Assertions.assertEquals(3, multiset.size());
        Assertions.assertEquals(1, multiset.count("a"));
        Assertions.assertEquals(2, multiset.elementSet().size());
        multiset.remove("a");
        Assertions.assertEquals(2, multiset.size());
        Assertions.assertEquals(0, multiset.count("a"));
        Assertions.assertEquals(1, multiset.elementSet().size());

Remove Specific Number of Elements

In the below example, we remove all a from multiset by calling multiset.remove("a", 2):

        List<String> list = Lists.newArrayList("a", "a", "b", "b");
        Multiset<String> multiset = HashMultiset.create(list);
        Assertions.assertEquals(4, multiset.size());
        Assertions.assertEquals(2, multiset.count("a"));
        Assertions.assertEquals(2, multiset.elementSet().size());
        multiset.remove("a", 2);
        Assertions.assertEquals(2, multiset.size());
        Assertions.assertEquals(0, multiset.count("a"));
        Assertions.assertEquals(1, multiset.elementSet().size());

Set Number of Elements

We can directly set the count of an element, as shwon in the below example, we remove all b from multiset by calling multiset.setCount("b", 2) and set number of element a as 9 by calling multiset.setCount("a", 9)

        List<String> list = Lists.newArrayList("a", "b");
        Multiset<String> multiset = HashMultiset.create(list);
        Assertions.assertEquals(2, multiset.size());
        Assertions.assertEquals(1, multiset.count("a"));
        Assertions.assertEquals(2, multiset.elementSet().size());
        multiset.setCount("a", 9);
        multiset.setCount("b", 0);
        Assertions.assertEquals(9, multiset.size());
        Assertions.assertEquals(9, multiset.count("a"));
        Assertions.assertEquals(0, multiset.count("b"))

Iterate Over Elements

The Multiset is backed with a Map, we can iterate the elements using a Map entry:

        List<String> list = Lists.newArrayList("a", "b");
        Multiset<String> multiset = HashMultiset.create(list);
        multiset.setCount("a", 9);
        multiset.setCount("b", 5);

        for (Multiset.Entry<String> entry : multiset.entrySet()) {
            System.out.println("element: " + entry.getElement() + ", count: " + entry.getCount());
        }

Read More