Apache Commons Collections – MultiValuedMap Interface
Apache Commons’s MultiValuedMap interface allows mapping a single key to multiple values in Java, unlike java.util.Map, where a key can only be associated with a single value.
In the previous post, we have seen how to implement our own Multimap class in Java using a map and a Collection. This post will discuss various utility methods provided by Apache Commons’s MultiValuedMap interface:
1. Using put(), get(), asMap() methods
1. We know that if we put two values into a java.util.Map using the same key, the first value will be overridden by the second value. This behavior enforces the map’s key to associate with only one value, which is sometimes undesirable. Apache Commons provides MultiValuedMap that adds the new value to the collection stored against the key to avoid it. Any put() operations on a key will not override the values set by the previous put() operations on that key.
2. The get() method of Apache Commons’s MultiValuedMap interface returns a collection holding all values associated with the specified key. When containsKey(key) is false, an empty collection is returned, unlike Map.get(), which returns a null value. Please note that the underlying MultiValuedMap gets updated on doing any changes to the returned collection, and vice versa.
3. We can also convert the MultiValuedMap<K,V> to Map<K,Collection<V>> using asMap() method provided by MultiValuedMap. Any changes made to the returned map or the collections that serve as its values will update the underlying MultiValuedMap and vice versa.
Following is a simple Java program to demonstrate Apache Commons’s MultiValuedMap class in Java.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
import org.apache.commons.collections4.MultiValuedMap; import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; import java.util.Arrays; import java.util.Collection; import java.util.Map; class Main { // Demonstrate Apache Commons Collections `MultiValuedMap` interface in Java public static void main(String[] args) { // Constructs an empty `MultiValuedMap` MultiValuedMap<String, String> multiValuedMap = new ArrayListValuedHashMap<>(); // `put(K, V)` adds the value to the collection stored against the key multiValuedMap.put("Zachary", "Taylor"); multiValuedMap.put("Grover", "Cleveland"); // `putAll(K, Iterable)` adds a mapping to the specified key for all // values contained in the given Iterable multiValuedMap.putAll("John", Arrays.asList("Adams", "Tyler")); multiValuedMap.putAll("George", Arrays.asList("Washington", "Bush")); // get `java.util.Map` representation of the `MultiValuedMap` Map<String, Collection<String>> map = multiValuedMap.asMap(); // do some change map.get("John").add("Kennedy"); System.out.println("John: " + map.get("John")); // the `MultiValuedMap` also gets updated System.out.println("John: " + multiValuedMap.get("John")); } } |
Output:
John: [Adams, Tyler, Kennedy]
George: [Washington, Bush]
The above program uses ArrayListValuedHashMap implementation of MultiValuedMap interface that internally uses an ArrayList to store the values for a given key and allows the duplicate key-value pairs. Some implementations, like HashSetValuedHashMap, don’t allow duplicates. It all depends on the underlying data structure. For instance, an ArrayList supports duplicates, whereas a HashSet doesn’t.
2. Iterate over the MultiValuedMap
MultiValuedMap interface provides keySet(), entries(), values(), and keys() methods which are similar to the corresponding view collections of Map. To illustrate, consider the following MultiValuedMap used in the following functions as input to them.
Zachary –> Taylor
John –> Adams, Tyler, Kennedy
George –> Washington, Bush
⮚ Using keySet()
keySet() method returns a set view of the keys contained in this MultiValuedMap.
|
1 2 3 4 5 6 7 |
// Iterate over Apache Commons's `MultiValuedMap` using `keySet()` method public static<K, V> void iterate(MultiValuedMap<K, V> multiValuedMap) { for (K key: multiValuedMap.keySet()) { System.out.println(key + ": " + multiValuedMap.get(key)); } } |
Output:
George: [Washington, Bush]
Zachary: [Taylor]
John: [Adams, Tyler, Kennedy]
⮚ Using entries()
entries() method returns a Collection view of the mappings contained in this MultiValuedMap.
|
1 2 3 4 5 6 7 |
// Iterate over Apache Commons's `MultiValuedMap` using `entries()` method public static<K, V> void iterate(MultiValuedMap<K, V> multiValuedMap) { for (Map.Entry<K, V> entry: multiValuedMap.entries()) { System.out.println(entry.getKey() + ": " + entry.getValue()); } } |
Output:
George: Washington
George: Bush
Zachary: Taylor
John: Adams
John: Tyler
John: Kennedy
⮚ Using keys() and values()
key() method returns a MultiSet view of the keys contained in this MultiValuedMap while the values() method returns a Collection view of all values contained in this MultiValuedMap.
|
1 2 3 4 5 6 7 8 9 10 |
// Iterate over Apache Commons's `MultiValuedMap` keys using `keys()` method // and values using `values()` method public static<K, V> void iterate(MultiValuedMap<K, V> multiValuedMap) { MultiSet<K> multiset = multiValuedMap.keys(); System.out.println(multiset); Collection<V> values = multiValuedMap.values(); System.out.println(values); } |
Output:
[George:2, Zachary:1, John:3]
[Washington, Bush, Taylor, Adams, Tyler, Kennedy]
3. Remove and Search keys/values in the MultiValuedMap
Apache Commons’s MultiValuedMap provides the remove() method that removes all values associated with the specified key. It also has the removeMapping() method that removes the specified key-value pair from the MultiValuedMap. But note that no method is included for replacing the existing values for a particular key.
For searching key, values, or key-value pairs, MultiValuedMap has three methods – containsKey(), containsValue() and containsEntry(), that checks if the MultiValuedMap contains at least one key-value pair with the specified key, specified value, and the specified key-value pair, respectively.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
import org.apache.commons.collections4.MultiValuedMap; import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; import java.util.Arrays; class Main { // Demonstrate `remove()`, `removeMapping()`, `containsKey()`, `containsMapping()` // and `containsValue()` methods of Apache Commons's `MultiValuedMap` public static void main(String[] args) { // Constructs an empty `MultiValuedMap` MultiValuedMap<String, String> multiValuedMap = new ArrayListValuedHashMap<>(); multiValuedMap.putAll("John", Arrays.asList("Adams", "Kennedy")); multiValuedMap.putAll("George", Arrays.asList("Washington", "Bush")); System.out.println("MultiValuedMap: " + multiValuedMap + '\n'); // remove() removes all values associated with the specified key multiValuedMap.remove("George"); // check if the `MultiValuedMap` contains at least one key-value pair // with the "George" as the key if (!multiValuedMap.containsKey("George")) { System.out.println("George key is deleted."); } // removeMapping() removes the specified key-value mapping from the map multiValuedMap.removeMapping("John", "Adams"); // check if the `MultiValuedMap` contains at least one key-value pair // with "John" as the key and "Adams" as the value if (!multiValuedMap.containsMapping("John", "Adams")) { System.out.println("John Adams is removed."); } // check if the `MultiValuedMap` contains at least one key-value pair // with the "Kennedy" as the value if (multiValuedMap.containsValue("Kennedy")) { System.out.println("John Kennedy is still there!"); } System.out.println("\nMultiValuedMap: " + multiValuedMap); } } |
Output:
MultiValuedMap: {George=[Washington, Bush], John=[Adams, Kennedy]}
George key is deleted.
John Adams is removed.
John Kennedy is still there!
MultiValuedMap: {John=[Kennedy]}
We have seen that MultiValuedMap interface is implemented as Map<K,Collection<V>>. So one would expect the size() method to return the total number of distinct keys. Instead, it returns the exact number of key-value pairs contained in it. We should use keySet().size() or asMap().size() to get the total number of distinct keys.
That’s all about Apache Commons Collections MultiValuedMap Interface in Java.
Also See:
Reference: MultiValuedMap (Apache Commons Collections 4.1 API)
Thanks for reading.
To share your code in the comments, please use our online compiler that supports C, C++, Java, Python, JavaScript, C#, PHP, and many more popular programming languages.
Like us? Refer us to your friends and support our growth. Happy coding :)