文章目录
java8 发布后,map类库增加了多个新的方法,利用这些新方法能更加便利地操纵Map中的数据
新增的方法有:
getOrDefault,forEach,compute,computeIfAbsent,computeIfPresent,merge,putIfAbsent,remove(key,value),replace,replaceAll
getOrDefault
getOrDefault() 方法获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值。
语法:
hashmap.get(Object key, V defaultValue)
参数说明:
- key - 键
- defaultValue - 当指定的key并不存在映射关系中,则返回的该默认值
返回值:
返回 key 相映射的的 value,如果给定的 key 在映射关系中找不到,则返回指定的默认值。
模拟数据:
Map<String, Integer> map = new LinkedHashMap<>(4);
map.put("lisa", 1);
map.put("jone", 2);
map.put("selina", 3);
java8之前的方式
Map<String, Integer> map = new HashMap<>(4);
map.put("lisa", 1);
int lisaValue = 0;
if (map.containsKey("lisa")) {
lisaValue = map.get("lisa");
}
System.out.println(lisaValue);
java8
// key为 lisa 的映射存在则返回对应value,否则返回默认值-1
Integer java8lisaValue = map.getOrDefault("lisa", -1);
// 1
System.out.println(java8lisaValue);
// key为 adas 的映射存在则返回对应value,否则返回默认值-999
Integer adasValue = map.getOrDefault("adas", -999);
// adas
System.out.println(adasValue);
forEach
foreach 可以让我们以Lambda的方式快速遍历映射集(map)
语法:
map.forEach(BiConsumer<K, V> action)
参数说明:
BiConsumer
- java8新提供的函数式接口,我们可以定义遍历消费逻辑
返回值:
无
模拟数据:
Map<String, Integer> map = new LinkedHashMap<>(4);
map.put("lisa", 1);
map.put("jone", 2);
map.put("selina", 3);
java8之前的方式
这种是以前Map遍历获取键值对信息最高效的方式,因为每组键值对只需遍历一次,但写法较为古老
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + "==" + entry.getValue());
}
java8
实际上Java8 map的foreach底层仍是用的entrySet
,只是上层用了BiConsumer
函数式接口,简化了我们直接遍历的代码。
map.forEach((k, v) -> System.out.println(k + "=" + v));
具体实现如下:
compute
尝试计算指定键及其当前映射值的映射(如果没有当前映射,则返回null)
公式:
map.compute(K key, BiFunction remappingFunction)
参数说明:
- key - 键
- remappingFunction - 重新映射函数,用于重新计算值
返回值
如果 key 对应的 value 不存在,则返回该 null,如果存在,则返回通过 remappingFunction 重新计算后的值并保存到映射集中(如重新计算后的值为Null,不会保存,且会将该映射从映射集中删除)。
模拟数据:
Map<String, Integer> map = new LinkedHashMap<>(4);
map.put("lisa", 1);
map.put("jone", 2);
map.put("selina", 3);
java8 之前操作
private static Integer computeBefore(String key, Integer newValue) {
Map<String, Integer> map = new LinkedHashMap<>(4);
map.put("lisa", 1);
map.put("jone", 2);
map.put("selina", 3);
Integer oldValue = map.get(key);
if (newValue != null) {
if (map.containsKey(key) && oldValue != null) {
map.remove(key);
}
return null;
} else {
map.put(key, newValue);
return newValue;
}
}
java8操作
Key在Map中存在
// jone key存在,且 新value不为null,则会返回最新jone对应的value (v + 234),并添加到映射集map中
Integer joneNewValue = map.compute("jone", (k, v) -> v == null ? 0 : v + 234);
// joneNewValue:236
System.out.println("joneNewValue:" + joneNewValue);
// {lisa=1, jone=236, selina=3}
System.out.println(map);
System.out.println("================");
// jone key存在,且 新value为null,则会返回最新jone对应的value null,并将映射在原集中删除
Integer joneNewValue2 = map.compute("jone", (k, v) -> null);
// joneNewValue2:null
System.out.println("joneNewValue2:" + joneNewValue2);
// 此时会 移除 KEY jone
// {lisa=1, selina=3}
System.out.println(map);
Key在Map中不存在
// asd key不存在,且 新value不为null,则会返回最新asd对应的value 111,并保存到映射集map中
Integer asdNewValue = map.compute("asd", (k, v) -> 111);
// asdNewValue:111
System.out.println("asdNewValue:" + asdNewValue);
// {lisa=1, selina=3, asd=111}
System.out.println(map);
System.out.println("================");
// box key不存在,且 新value为null,则会返回null, 不保存到映射集map中
Integer boxNewValue = map.compute("box", (k, v) -> null);
// boxNewValue:null
System.out.println("boxNewValue:" + boxNewValue);
// {lisa=1, selina=3, asd=111}
System.out.println(map);
computeIfAbsent
如果指定的KEY 的键值对(k,v)不存在,或者 对应的Value 为空,则将键值对新增至映射集(Map)中
语法:
map.computeIfAbsent(K key, Function remappingFunction)
参数说明:
- key - 键
- remappingFunction - 重新映射函数,用于重新计算值
返回值:
如果 key 对应的 value 不存在,则使用获取 remappingFunction 重新计算后的值,并保存为该 key 的 value,否则返回 value。
模拟数据:
Map<String, Integer> map = new LinkedHashMap<>(4);
map.put("lisa", 1);
map.put("jone", 2);
map.put("selina", 3);
map.put("ddd", null);
java8 之前操作
Integer lisaValue = map.get("adas");
if ( !map.containsKey("adas")|| map.get("adas") == null) {
map.put("adas", 2345);
}
java8操作
// 原映射集无 key为 adas的键值对,且 新key adas 对应的 value 不为null (2345) 则会将其添加到map映射集中并返回该值
Integer adas = map.computeIfAbsent("adas", x -> 2345);
// 2345
System.out.println(adas);
// {lisa=1, jone=2, selina=3, ddd=null, adas=2345}
System.out.println(map);
System.out.println("--------------");
// 原映射集无 key为 dml的键值对,且 新key ml 对应的 value 为null,则忽略添加,并返回null
Integer dmlValue = map.computeIfAbsent("dml", x -> null);
// null
System.out.println(dmlValue);
// {lisa=1, jone=2, selina=3, ddd=null, adas=2345}
System.out.println(map);
System.out.println("--------------");
// 原映射集有 Key为 ddd的键值对,但ddd对应的value 为空,如果我们再次添加有效value到ddd,则会将原键值对覆盖
Integer dddNewValue = map.computeIfAbsent("ddd", x -> 0);
// 0
System.out.println(dddNewValue);
// {lisa=1, jone=2, selina=3, ddd=0, adas=2345}
System.out.println(map);
computeIfPresent
如果指定KEY的映射存在且Value非null,则将指定KEY的原Value,替换为现在的Value,保存存在映射集中,如果现Value为null,会将指定KEY的映射删除
语法:
map.computeIfPresent(K key, BiFunction remappingFunction)
参数说明:
- key - 键
- remappingFunction - 重新映射函数,用于重新计算值
返回值:
如果 key 对应的 value 不存在,则返回该 null,如果存在,则返回通过 remappingFunction 重新计算后的值。
模拟数据:
Map<String, Integer> map = new LinkedHashMap<>(4);
map.put("lisa", 1);
map.put("jone", 2);
map.put("selina", 3);
map.put("ddd", null);
java8之前操作
if (map.get("selina") != null) {
Integer oldValue = map.get("selina");
Integer newValue = 1232312;
if (newValue != null) {
map.put("selina", newValue);
} else {
map.remove("selina");
}
}
java8
// 原映射集中存在对应KEY ,原Value不为null,现value不为null,则覆盖原来 键值对映射
Integer selinaNewValue = map.computeIfPresent("selina", (k, v) -> 888999);
// 888999
System.out.println(selinaNewValue);
// {lisa=1, jone=2, selina=888999, ddd=null}
System.out.println(map);
System.out.println("-------------------");
// 原映射集中存在对应KEY ,原Value不为null,现value为null,则移除对应键值对
Integer selinaNewValue2 = map.computeIfPresent("selina", (k, v) -> null);
// null
System.out.println(selinaNewValue2);
// 移除了selina
System.out.println(map);
System.out.println("-------------------");
// 原映射集中存在对应KEY ,原Value为null,现value 不为null, 对原映射集不做任何操作
Integer dddNewValue = map.computeIfPresent("ddd", (k, v) -> 2222222);
System.out.println(dddNewValue);
System.out.println(map);
System.out.println("-------------------");
// 原映射集中不存在对应KEY ,现value 不为null 对原映射集不做任何操作
Integer mqNewValue = map.computeIfPresent("mq", (k, v) -> -1);
System.out.println(mqNewValue);
System.out.println(map);
merge
merge() 方法会先判断指定的 key 是否存在,如果不存在,则添加键值对到 hashMap 中,如果存在则根据逻辑重新映射该KEY键值对(如何合并相同KEY的新旧VALUE)
语法:
map.merge(key, value, remappingFunction)
参数说明:
- key - 键
- value - 值
- remappingFunction - 重新映射函数,用于重新计算值
返回值:
如果 key 对应的 value 不存在,则返回该 value 值,如果存在,则返回通过 remappingFunction 重新计算后的值。
模拟数据:
Map<String, Integer> map = new LinkedHashMap<>(4);
map.put("lisa", 1);
map.put("jone", 2);
map.put("selina", 3);
map.put("ddd", null);
我们都知道,Map 的KEY,如果相同了,后插入的值会覆盖新的值
Map<String, Integer> map = new LinkedHashMap<>(4);
map.put("lisa", 1);
map.put("jone", 2);
map.put("selina", 3);
// {lisa=1, jone=2, selina=3}
System.out.println(map);
map.put("lisa", 2);
// {lisa=2, jone=2, selina=3}
System.out.println(map);
merge,可以让我们根据自己选择如何处理相同KEY的值,类似于冲突合并(怎么合并,自己决定)
// 采用旧值
map.merge("lisa", 100, (oldValue, newValue) -> oldValue);
// 采用新值
map.merge("lisa", 100, (oldValue, newValue) -> newValue);
// 新旧值逻辑处理合并
map.merge("lisa", 100, (oldValue, newValue) -> oldValue + newValue);
map.merge("lisa", 100, Integer::sum);
注意:
java8 Stream Collectors.toMap() 方法便要我们去合并冲突,否则如果出现相同KEY的数据,或者Value为null,程序会报错!
User adas = new User("adas", 23);
User adas2 = new User("adas", 28);
User mlg = new User("mlg", 34);
ArrayList<User> list = new ArrayList<>();
list.add(adas);
list.add(adas2);
list.add(mlg);
Map<String, Integer> userMap = list.stream().collect(Collectors.toMap(User::getName, User::getValue));
System.out.println(userMap);
提示我们键冲突了!
解决:
Map<String, Integer> userMap = list.stream()
.filter(x->x.name!=null && x.value!=null)
// 这里采用新值覆盖旧值
.collect(Collectors.toMap(User::getName, User::getValue,(oldValue,newValue)->newValue));
// {adas=28, mlg=34}
System.out.println(userMap);
putIfAbsent
putIfAbsent() 方法会先判断指定的键(key)是否存在,不存在则将键/值对插入到映射集中,并返回null,存在则返回原本Value
语法:
map.putIfAbsent(K key, V value)
参数说明:
- key - 键
- value - 值
返回值:
如果所指定的 key 已经在Map 中存在,返回和这个 key 值对应的 value, 如果所指定的 key 在Map 中不存在,则返回 null。
注意如果指定 key 之前已经和一个 null 值相关联了 ,则该方法也返回 null。
模拟数据:
Map<String, Integer> map = new LinkedHashMap<>(4);
map.put("lisa", 1);
map.put("jone", 2);
map.put("selina", 3);
java8 之前写法
Integer newValue = 222;
Integer joneValue = map.get("jone");
if (joneValue == null) {
joneValue = map.put("lisa", newValue);
} else {
joneValue = joneValue;
}
java8
// selina 在源映射集中不存在,则返回null 做插入操作
Integer adasValue = map.putIfAbsent("adas", 1);
System.out.println(adasValue);
System.out.println(map);
System.out.println("----------");
// selina 在源映射集中存在,则返回原值 不做插入操作
Integer selinaValue = map.putIfAbsent("selina", 33333);
System.out.println(selinaValue);
System.out.println(map);
remove(key,value)
当指定的 KEY 与VALUE 在映射集中存在,且为绑定的键值对关系时,才移除
语法:
map.remove(K key, V value)
参数说明:
- key - 键
- value - 值
返回值:
仅当 key-value 映射存在,且二者为绑定关系时,才会移除该数据,返回true,其他情况为false
模拟数据:
Map<String, Integer> map = new LinkedHashMap<>(4);
map.put("lisa", 1);
演示
// lisa-2 无映射关系,因为不会移除
map.remove("lisa", 2);
// {lisa=1}
System.out.println(map);
replace
replace() 方法替换 映射集中是指定的 key 对应的 value。
语法:
map.replace(K key, V oldValue, V newValue)
参数说明:
- key - 键
- oldValue - 旧的 value 值
- newValue - 新的 value 值
返回值:
如果 oldValue 不存在,对 key 对应对 value 执行替换,返回 key 对应的旧值,如果存在则替换,并返回旧值。
如果 KEY 不存在,则不做任何操作,返回null
模拟数据:
Map<String, Integer> map = new LinkedHashMap<>(4);
map.put("lisa", 1);
演示
// key 存在 且原 value 不为null
Integer lisaOldValue = map.replace("lisa", 333);
// 返回原来旧值 1
System.out.println(lisaOldValue);
// lisa的值已被替换 {lisa=333, hobo=null}
System.out.println(map);
System.out.println("___________________");
// key 存在 且原 value 为null
Integer hoboOldValue = map.replace("hobo", -1);
// 返回旧值 null
System.out.println(hoboOldValue);
// hobo的值已被替换 {lisa=333, hobo=-1}
System.out.println(map);
System.out.println("___________________");
// key 不存在
Integer adasOldValue = map.replace("adas", -1);
// null
System.out.println(adasOldValue);
// 未变 {lisa=333, hobo=-1}
System.out.println(map);
replaceAll
replaceAll() 方法将 映射集中的所有映射Value替换成给定的函数所执行的结果
语法:
map.replaceAll(Bifunction<K, V> function)
**注:**hashmap 是 HashMap 类的一个对象。
参数说明:
- function - 函数式接口实例,生成映射对函数
返回值:
无,只会对映射集中的值做替换处理。
模拟数据:
Map<String, Integer> map = new LinkedHashMap<>(4);
map.put("lisa", 1);
map.put("jone", 2);
map.put("selina", 3);
map.put("qq", null);
演示
// replaceAll之前:{lisa=1, jone=2, selina=3, qq=null}
System.out.println("replaceAll之前:" + map);
map.replaceAll((k, v) -> v == null ? -1 : v * 100);
// replaceAll之后:{lisa=100, jone=200, selina=300, qq=-1}
System.out.println("replaceAll之后:" + map);
values
values() 方法返回映射中所有 value 组成的集合
语法:
hashmap.values()
参数说明:
- 无
返回值:
返回 Map 中所有 value 值所组成的集合
模拟数据:
Map<String, Integer> map = new LinkedHashMap<>(4);
map.put("lisa", 1);
map.put("jone", 2);
map.put("selina", 3);
map.put("qq", null);
演示
// [lisa, jone, selina, qq]
System.out.println(map.keySet());
// [1, 2, 3, null]
System.out.println(map.values());