Apache Commons Collections MapUtils类简介
1. 简介
MapUtils是 Apache Commons Collections 项目中可用的工具之一。
简单地说,它提供了实用方法和装饰器来处理java.util.Map和java.util.SortedMap实例。
2. 设置
让我们从添加依赖项 开始:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.1</version>
</dependency>
3. 实用方法
3.1. 从Array创建Map
现在,让我们设置用于创建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;
//...
}
让我们看看如何从二维数组创建Map:
@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"));
}
我们也可以使用一维数组。在这种情况下,数组被视为备用索引中的键和值:
@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"));
}
3.2. 打印Map的内容
很多时候,在调试或调试日志中,我们想打印整个Map:
@Test
public void whenVerbosePrintMap_thenMustPrintFormattedMap() {
MapUtils.verbosePrint(System.out, "Optional Label", this.colorMap);
}
结果:
Optional Label =
{
RED = #FF0000
BLUE = #0000FF
GREEN = #00FF00
}
我们还可以使用*debugPrint()*额外打印值的数据类型。
3.3. 获取值
MapUtils提供了一些方法,用于以null安全的方式从给定键的映射中提取值。
例如,getString()从Map中获取一个String。String值是通过toString()获得的。如果值为null或转换失败,我们可以选择指定要返回的默认值:
@Test
public void whenGetKeyNotPresent_thenMustReturnDefaultValue() {
String defaultColorStr = "COLOR_NOT_FOUND";
String color = MapUtils
.getString(this.colorMap, "BLACK", defaultColorStr);
assertEquals(color, defaultColorStr);
}
请注意,这些方法是null安全的,即它们可以安全地处理null map 参数:
@Test
public void whenGetOnNullMap_thenMustReturnDefaultValue() {
String defaultColorStr = "COLOR_NOT_FOUND";
String color = MapUtils.getString(null, "RED", defaultColorStr);
assertEquals(color, defaultColorStr);
}
即使地图为null ,这里的颜色也会得到COLOR_NOT_FOUND的值。
3.4. 反转Map
我们还可以轻松地反转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[] {}));
}
这会将colorMap反转为:
{
#00FF00 = GREEN
#FF0000 = RED
#0000FF = BLUE
}
如果源映射为多个键关联相同的值,则在反转后,其中一个值将随机成为键。
3.5. 空和空检查
如果Map为null或为空,isEmpty()方法返回true 。
safeAddToMap()方法防止向Map 添加空元素。
4. 装饰器
这些方法为Map添加了额外的功能。
在大多数情况下,最好不要存储对装饰 Map 的引用。
4.1. 固定大小的Map
*fixedSizeMap()*返回由给定地图支持的固定大小地图。元素可以更改,但不能添加或删除:
@Test(expected = IllegalArgumentException.class)
public void whenCreateFixedSizedMapAndAdd_thenMustThrowException() {
Map<String, String> rgbMap = MapUtils
.fixedSizeMap(MapUtils.putAll(new HashMap<>(), this.color1DArray));
rgbMap.put("ORANGE", "#FFA500");
}
4.2. predicatedMap
predicatedMap()方法返回一个Map确保所有持有的元素与提供的谓词匹配:
@Test(expected = IllegalArgumentException.class)
public void whenAddDuplicate_thenThrowException() {
Map<String, String> uniqValuesMap
= MapUtils.predicatedMap(this.colorMap, null,
PredicateUtils.uniquePredicate());
uniqValuesMap.put("NEW_RED", "#FF0000");
}
在这里,我们使用PredicateUtils.uniquePredicate()为值指定谓词。任何将重复值插入此映射的尝试都将导致java.lang。非法参数异常。
我们可以通过实现Predicate接口来实现自定义谓词。
4.3. lazyMap
*lazyMap()*返回一个映射,其中值在请求时被初始化。
如果传递给此映射的Map.get(Object)方法的键在映射中不存在,则Transformer实例将用于创建将与请求的键关联的新对象:
@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)));
}