Map处理利器 - MapUtil
JAVA开发 Map操作少不了,存储key-value键值对数据,常用来做缓存以及传输数据等,下面特别封装常用的方法
MapUtil
主要由下面部分组成:
1 提取
方法 | Description |
---|---|
extractSubMap(Map<K, O>, String) | 以参数 map的key为key,以参数 map value的指定extractPropertyName 属性值为值,拼装成新的map返回. |
extractSubMap(Map<K, O>, K[], String) | 以参数 map的key为key,以参数 mapvalue的指定extractPropertyName 属性值为值,拼装成新的map返回. |
1.1 extractSubMap(Map<K, O>, String)
以参数 map的key为key,以参数 map value的指定 extractPropertyName
属性值为值,拼装成新的map返回.
说明:
- 返回map的顺序,按照参数 map key的顺序示例:
```JAVA
Map<Long, User> map = new LinkedHashMap<>();
map.put(1L, new User(100L));
map.put(2L, new User(200L));
map.put(5L, new User(500L));
map.put(4L, new User(400L));
LOGGER.debug(JsonUtil.format(MapUtil.extractSubMap(map, "id")));
```
返回:
```JSON
{
"1": 100,
"2": 200,
"5": 500,
"4": 400
}
```
1.2 extractSubMap(Map<K, O>, K[], String)
以参数 map的key为key,以参数 mapvalue的指定extractPropertyName
属性值为值,拼装成新的map返回.
说明:
- 如果在抽取的过程中,map没有某个
includeKeys
,将会忽略该key的抽取,并输出 warn log - 如果参数
includeKeys
是null或者 empty,那么会抽取map所有的key - 返回map的顺序,按照参数
includeKeys
的顺序(如果includeKeys
是null,那么按照map key的顺序)示例:
Map<Long, User> map = new LinkedHashMap<>();
map.put(1L, new User(100L));
map.put(2L, new User(200L));
map.put(53L, new User(300L));
map.put(5L, new User(500L));
map.put(6L, new User(600L));
map.put(4L, new User(400L));
Long[] includeKeys = { 5L, 4L };
LOGGER.debug(JsonUtil.format(MapUtil.extractSubMap(map, includeKeys, "id")));
返回:
{
"5": 500,
"4": 400
}
典型示例:
private Map<Long, Long> constructPropertyIdAndItemPropertiesIdMap(
String properties,
Map<Long, PropertyValueSubViewCommand> itemPropertiesIdAndPropertyValueSubViewCommandMap){
Long[] itemPropertiesIds = StoCommonUtil.toItemPropertiesIdLongs(properties);
Map<Long, Long> itemPropertiesIdAndPropertyIdMap = MapUtil
.extractSubMap(itemPropertiesIdAndPropertyValueSubViewCommandMap, itemPropertiesIds, "propertyId");
return MapUtil.invertMap(itemPropertiesIdAndPropertyIdMap);
}
2 获得子Map
方法 | Description |
---|---|
getSubMap(Map<K, T>, K…) | 获得一个map 中的按照指定的key 整理成新的map. |
getSubMapExcludeKeys(Map<K, T>, K…) | 获得 sub map(去除不需要的keys). |
2.1 getSubMap(Map<K, T>, K…)
获得一个map 中的按照指定的key 整理成新的map.
说明:
- 返回的map为
LinkedHashMap
,key的顺序 按照参数 keys的顺序 - 如果循环的 key不在map key里面,则返回的map中忽略该key,并输出warn level log示例:
Map<String, Integer> map = new HashMap<>();
map.put("a", 3007);
map.put("b", 3001);
map.put("c", 3001);
map.put("d", 3003);
LOGGER.debug(JsonUtil.format(MapUtil.getSubMap(map, "a", "c")));
返回:
{
"a": 3007,
"c": 3001
}
2.2 getSubMapExcludeKeys(Map<K, T>, K…)
获得 sub map(去除不需要的keys).
说明:
- 返回值为
LinkedHashMap
,key的顺序 按照参数 map的顺序 - 如果
excludeKeys
中含有 map 中不存在的key,将会输出warn级别的log示例:
Map<String, Integer> map = new LinkedHashMap<>();
map.put("a", 3007);
map.put("b", 3001);
map.put("c", 3002);
map.put("g", -1005);
LOGGER.debug(JsonUtil.format(MapUtil.getSubMapExcludeKeys(map, "a", "g", "m")));
返回:
{
"b": 3001,
"c": 3002
}
3 构造
方法 | Description |
---|---|
newHashMap(int) | 创建 HashMap 实例,拥有足够的 "initial capacity" 应该控制expectedSize elements without growth. |
newLinkedHashMap(int) | 创建 LinkedHashMap 实例,拥有足够的 "initial capacity" 应该控制expectedSize elements without growth. |
3.1 newHashMap(int)
创建 HashMap
实例,拥有足够的 "initial capacity"
应该控制expectedSize elements without growth.
This behavior cannot be broadly guaranteed, but it is observed to be true for OpenJDK 1.7.It also can't be guaranteed that the method isn't inadvertently oversizing the returned map.
示例:
Map<String, String> newHashMap = MapUtil.newHashMap(3);
newHashMap.put("name", "feilong");
newHashMap.put("age", "18");
newHashMap.put("address", "shanghai");
使用该方法的好处:
- 简化代码书写方式 以前你可能需要这么写代码:
Map<String, Map<Long, List<String>>> map = new HashMap<String, Map<Long, List<String>>>(16);
如果你是使用JDK1.7或者以上,你可以使用钻石符:
Map<String, Map<Long, List<String>>> map = new HashMap<>(16);
不过只要你是使用1.5+,你都可以写成:
Map<String, Map<Long, List<String>>> map = MapUtil.newHashMap(16);
- 减少扩容次数 如果你要一次性初始一个能存放100个元素的map,并且不需要扩容,提高性能的话,你需要
Map<String, Map<Long, List<String>>> map = new HashMap<String, Map<Long, List<String>>>(100/0.75+1);
使用这个方法,你可以直接写成:
Map<String, Map<Long, List<String>>> map = MapUtil.newHashMap(100);
3.2 newLinkedHashMap(int)
创建 LinkedHashMap
实例,拥有足够的 "initial capacity"
应该控制 expectedSize elements without growth
.
This behavior cannot be broadly guaranteed, but it is observed to be true for OpenJDK 1.7.It also can't be guaranteed that the method isn't inadvertently oversizing the returned map.
示例:
Map<String, String> map = MapUtil.newLinkedHashMap(3);
map.put("name", "feilong");
map.put("age", "18");
map.put("address", "shanghai");
使用该方法的好处:
- 简化代码书写方式 以前你可能需要这么写代码:
Map<String, Map<Long, List<String>>> map = new LinkedHashMap<String, Map<Long, List<String>>>(16);
如果你是使用JDK1.7或者以上,你可以使用钻石符:
Map<String, Map<Long, List<String>>> map = new LinkedHashMap<>(16);
不过只要你是使用1.5+,你都可以写成:
Map<String, Map<Long, List<String>>> map = MapUtil.newLinkedHashMap(16);
- 减少扩容次数 如果你要一次性初始一个能存放100个元素的map,并且不需要扩容,提高性能的话,你需要
Map<String, Map<Long, List<String>>> map = new LinkedHashMap<String, Map<Long, List<String>>>(100/0.75+1);
使用这个方法,你可以直接写成:
Map<String, Map<Long, List<String>>> map = MapUtil.newLinkedHashMap(100);
4 辅助put
方法 | Description |
---|---|
putAllIfNotNull(Map<K, V>, Map<? extends K, ? extends V>) | 仅当 null != map && null != m ,才会进行 map.putAll(m) 操作 |
putIfValueNotNull(Map<K, V>, K, V) | 仅当 null != map 并且 null != value 才将key/value put到map中. |
putIfValueNotNullOrEmpty(Map<K, V>, K, V) | 仅当 null != map 并且 isNotNullOrEmpty(value) 才将key/value put到map中. |
putMultiValue(Map<K, List<V>>, K, V) | 往 map 中put 指定 key value(多值形式). |
putSumValue(Map<K, Integer>, K, Integer) | 将key和value 累加的形式put到 map中,如果map中存在key,那么累加value值;如果不存在那么直接put. |
4.1 putIfValueNotNull(Map<K, V>, K, V)
仅当 null != map
并且 null != value
才将key/value put到map中.
说明:
- 如果 map 是null,什么都不做
- 如果 value 是null,也什么都不做
- 如果 key 是null,依照map的key是否允许是null的 规则
4.2 putAllIfNotNull(Map<K, V>, Map<? extends K, ? extends V>)
仅当 null != map && null != m
,才会进行 map.putAll(m)
操作
重构:
对于以下代码:
if (isNotNullOrEmpty(specialSignMap)){
map.putAll(specialSignMap);
}
可以重构成:
MapUtil.putAllIfNotNull(map, specialSignMap)
4.3 putIfValueNotNullOrEmpty(Map<K, V>, K, V)
仅当 null != map
并且 isNotNullOrEmpty(value)
才将key/value
put到map中.
说明:
- 如果 map 是null,什么都不做
- 如果 value 是null或者empty,也什么都不做
- 如果 key 是null,依照map的key是否允许是null的规则重构:对于以下代码:
if (isNotNullOrEmpty(taoBaoOAuthLoginForCodeEntity.getState())){
nameAndValueMap.put("state", taoBaoOAuthLoginForCodeEntity.getState());
}
可以重构成:
MapUtil.putIfValueNotNullOrEmpty(nameAndValueMap, "state", taoBaoOAuthLoginForCodeEntity.getState());
4.4 putSumValue(Map<K, Integer>, K, Integer)
将key和value 累加的形式put到 map中,如果map中存在key,那么累加value值;如果不存在那么直接put.
示例:
Map<String, Integer> map = new HashMap<>();
MapUtil.putSumValue(map, "1000001", 5);
MapUtil.putSumValue(map, "1000002", 5);
MapUtil.putSumValue(map, "1000002", 5);
LOGGER.debug(JsonUtil.format(map));
返回:
{
"1000001": 5,
"1000002": 10
}
重构:对于以下代码:
if (disadvantageMap.containsKey(disadvantageToken)){
disadvantageMap.put(disadvantageToken, disadvantageMap.get(disadvantageToken) + 1);
}else{
disadvantageMap.put(disadvantageToken, 1);
}
可以重构成:
MapUtil.putSumValue(disadvantageMap, disadvantageToken, 1);
4.5 putMultiValue(Map<K, List<V>>, K, V)
往 map 中put 指定 key value(多值形式).
说明:
- map已经存在相同名称的key,那么value以list的形式累加.
- 如果map中不存在指定名称的key,那么会构建一个ArrayList示例:
Map<String, List<String>> mutiMap = newLinkedHashMap(2);
MapUtil.putMultiValue(mutiMap, "name", "张飞");
MapUtil.putMultiValue(mutiMap, "name", "关羽");
MapUtil.putMultiValue(mutiMap, "age", "30");
LOGGER.debug(JsonUtil.format(mutiMap));
返回:
{
"name": [
"张飞",
"关羽"
],
"age": ["30"]
}
对于下面的代码:
private void putItemToMap(Map<String, List<Item>> map,String tagName,Item item){
List<Item> itemList = map.get(tagName);
if (isNullOrEmpty(itemList)){
itemList = new ArrayList<Item>();
}
itemList.add(item);
map.put(tagName, itemList);
}
可以重构成:
private void putItemToMap(Map<String, List<Item>> map,String tagName,Item item){
com.feilong.core.util.MapUtil.putMultiValue(map, tagName, item);
}
5 删除
方法 | Description |
---|---|
removeKeys(Map<K, V>, K…) | 删除 map 的指定的 keys. |
5.1 removeKeys(Map<K, V>, K…)
删除 map 的指定的 keys.
注意
- 直接操作的是参数map,迭代 keys,
- 如果 map包含key,那么直接调用
Map.remove(Object)
, - 如果不包含,那么输出warn级别日志示例:
Map<String, String> map = newLinkedHashMap(3);
map.put("name", "feilong");
map.put("age", "18");
map.put("country", "china");
LOGGER.debug(JsonUtil.format(MapUtil.removeKeys(map, "country")));
返回:
{
"name": "feilong",
"age": "18"
}
6 转换
方法 | Description |
---|---|
toArrayValueMap(Map<K, String>) | 将单值的singleValueMap 转成多值的map. |
toSingleValueMap(Map<K, V[]>) | 将多值的arrayValueMap 转成单值的map. |
6.1 toSingleValueMap(Map<K, V[]>)
将多值的 arrayValueMap
转成单值的map.
示例1:
Map<String, String[]> arrayValueMap = new LinkedHashMap<>();
arrayValueMap.put("province", new String[] { "江苏省" });
arrayValueMap.put("city", new String[] { "南通市" });
LOGGER.info(JsonUtil.format(ParamUtil.toSingleValueMap(arrayValueMap)));
返回:
{
"province": "江苏省",
"city": "南通市"
}
如果 arrayValueMap
其中有key的值是多值的数组,那么转换到新的map中的时候,value取第一个值,
示例2:
Map<String, String[]> arrayValueMap = new LinkedHashMap<>();
arrayValueMap.put("province", new String[] { "浙江省", "江苏省" });
arrayValueMap.put("city", new String[] { "南通市" });
LOGGER.info(JsonUtil.format(ParamUtil.toSingleValueMap(arrayValueMap)));
返回:
{
"province": "浙江省",
"city": "南通市"
}
说明:
- 返回的map是 提取参数
arrayValueMap
的key做为key,value数组的第一个元素做value - 返回的是
LinkedHashMap
,保证顺序和参数arrayValueMap
顺序相同 - 和该方法正好相反的是
toArrayValueMap(Map)
6.2 toArrayValueMap(Map<K, String>)
将单值的 singleValueMap
转成多值的map.
示例:
Map<String, String> singleValueMap = new LinkedHashMap<>();
singleValueMap.put("province", "江苏省");
singleValueMap.put("city", "南通市");
LOGGER.info(JsonUtil.format(ParamUtil.toArrayValueMap(singleValueMap)));
返回:
{
"province": ["江苏省"],
"city": ["南通市"]
}
说明:
- 返回的是
LinkedHashMap
,保证顺序和参数singleValueMap
顺序相同 - 和该方法正好相反的是
toSingleValueMap(Map)
7 反转
方法 | Description |
---|---|
invertMap(Map<K, V>) |
7.1 invertMap(Map<K, V>)
将 map 的key和value互转.
说明:
- 这个操作map预先良好的定义.
- 如果传过来的map,不同的key有相同的value,那么返回的map(key)只会有一个(value),其他重复的key被丢掉了示例:
Map<String, Integer> map = new HashMap<>();
map.put("a", 3007);
map.put("b", 3001);
map.put("c", 3001);
map.put("d", 3003);
LOGGER.debug(JsonUtil.format(MapUtil.invertMap(map)));
返回:
{
"3001": "c",
"3007": "a",
"3003": "d"
}
可以看出 b元素被覆盖了