
Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:
Once the early-adopter seats are all used, the price will go up and stay at $33/year.
Last updated: August 30, 2024
MapUtils is one of the tools available in the Apache Commons Collections project.
Simply put, it provides utility methods and decorators to work with java.util.Map and java.util.SortedMap instances.
Let’s start by adding the dependency:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.5.0-M2</version>
</dependency>
Now, let’s set up arrays that we will use for creating a map:
public class MapUtilsTest {
private String[][] color2DArray = new String[][] {
{"RED", "#FF0000"},
{"GREEN", "#00FF00"},
{"BLUE", "#0000FF"}
};
private String[] color1DArray = new String[] {
"RED", "#FF0000",
"GREEN", "#00FF00",
"BLUE", "#0000FF"
};
private Map<String, String> colorMap;
//...
}
Let’s see how we can create a map from a two-dimensional array:
@Test
public void whenCreateMapFrom2DArray_theMapIsCreated() {
this.colorMap = MapUtils.putAll(
new HashMap<>(), this.color2DArray);
assertThat(
this.colorMap,
is(aMapWithSize(this.color2DArray.length)));
assertThat(this.colorMap, hasEntry("RED", "#FF0000"));
assertThat(this.colorMap, hasEntry("GREEN", "#00FF00"));
assertThat(this.colorMap, hasEntry("BLUE", "#0000FF"));
}
We could also use a one-dimensional array. In that case, the array is treated as keys and values in alternate indices:
@Test
public void whenCreateMapFrom1DArray_theMapIsCreated() {
this.colorMap = MapUtils.putAll(
new HashMap<>(), this.color1DArray);
assertThat(
this.colorMap,
is(aMapWithSize(this.color1DArray.length / 2)));
assertThat(this.colorMap, hasEntry("RED", "#FF0000"));
assertThat(this.colorMap, hasEntry("GREEN", "#00FF00"));
assertThat(this.colorMap, hasEntry("BLUE", "#0000FF"));
}
Many times while debugging or in debug logs, we would like to print the entire map:
@Test
public void whenVerbosePrintMap_thenMustPrintFormattedMap() {
MapUtils.verbosePrint(System.out, "Optional Label", this.colorMap);
}
And the result:
Optional Label =
{
RED = #FF0000
BLUE = #0000FF
GREEN = #00FF00
}
We can also use debugPrint() which additionally prints the data types of the values.
MapUtils provides some methods for extracting value from a map for a given key in a null-safe manner.
For example, getString() gets a String from the Map. The String value is obtained via toString(). We can optionally specify the default value to be returned if the value is null or if the conversion fails:
@Test
public void whenGetKeyNotPresent_thenMustReturnDefaultValue() {
String defaultColorStr = "COLOR_NOT_FOUND";
String color = MapUtils
.getString(this.colorMap, "BLACK", defaultColorStr);
assertEquals(color, defaultColorStr);
}
Note that these methods are null-safe i.e. they can safely handle the null map parameter:
@Test
public void whenGetOnNullMap_thenMustReturnDefaultValue() {
String defaultColorStr = "COLOR_NOT_FOUND";
String color = MapUtils.getString(null, "RED", defaultColorStr);
assertEquals(color, defaultColorStr);
}
Here the color would get the value as COLOR_NOT_FOUND even though the map is null.
We can also easily reverse a map:
@Test
public void whenInvertMap_thenMustReturnInvertedMap() {
Map<String, String> invColorMap = MapUtils.invertMap(this.colorMap);
int size = invColorMap.size();
Assertions.assertThat(invColorMap)
.hasSameSizeAs(colorMap)
.containsKeys(this.colorMap.values().toArray(new String[] {}))
.containsValues(this.colorMap.keySet().toArray(new String[] {}));
}
This would invert the colorMap to:
{
#00FF00 = GREEN
#FF0000 = RED
#0000FF = BLUE
}
If the source map associates same value for multiple keys then after inversion one of the values will become a key randomly.
isEmpty() method returns true if a Map is null or empty.
safeAddToMap() method prevents addition of null elements to a Map.
These methods add additional functionality to a Map.
In most cases, it’s good practice not to store the reference to the decorated Map.
fixedSizeMap() returns a fixed-size map backed by the given map. Elements can be changed but not added or removed:
@Test(expected = IllegalArgumentException.class)
public void whenCreateFixedSizedMapAndAdd_thenMustThrowException() {
Map<String, String> rgbMap = MapUtils
.fixedSizeMap(MapUtils.putAll(new HashMap<>(), this.color1DArray));
rgbMap.put("ORANGE", "#FFA500");
}
The predicatedMap() method returns a Map ensures that all held elements match the provided predicate:
@Test(expected = IllegalArgumentException.class)
public void whenAddDuplicate_thenThrowException() {
Map<String, String> uniqValuesMap
= MapUtils.predicatedMap(this.colorMap, null,
PredicateUtils.uniquePredicate());
uniqValuesMap.put("NEW_RED", "#FF0000");
}
Here, we specified the predicate for values using PredicateUtils.uniquePredicate(). Any attempt to insert a duplicate value into this map will result in java.lang.IllegalArgumentException.
We can implement custom predicates by implementing the Predicate interface.
lazyMap() returns a map where values are initialized when requested.
If a key passed to this map’s Map.get(Object) method is not present in the map, the Transformer instance will be used to create a new object that will be associated with the requested key:
@Test
public void whenCreateLazyMap_theMapIsCreated() {
Map<Integer, String> intStrMap = MapUtils.lazyMap(
new HashMap<>(),
TransformerUtils.stringValueTransformer());
assertThat(intStrMap, is(anEmptyMap()));
intStrMap.get(1);
intStrMap.get(2);
intStrMap.get(3);
assertThat(intStrMap, is(aMapWithSize(3)));
}
In this quick tutorial, we have explored the Apache Commons Collections MapUtils class and we looked at various utility methods and decorators that can simplify various common map operations.