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());
}