jdk8这样使用Map
2019-06-22 本文已影响3人
zheng93775
jdk8中接口增加了default方法,可以在接口里实现简单的公共逻辑。本篇文章介绍一下java.util.Map里新出的default方法,平常写代码的时候很可能能用上,可以帮助我们写出更优雅的代码。
getOrDefault
获取key对应的value,当key不存在时,返回默认值
// 源码
default V getOrDefault(Object key, V defaultValue) {
V v;
return (((v = get(key)) != null) || containsKey(key))
? v
: defaultValue;
}
// 测试
@Test
public void getOrDefault() {
Map<String, Integer> map = new HashMap<>();
map.put("A", 1);
map.put("B", 2);
map.put("C", 3);
Integer resultB = map.getOrDefault("B", 0);
System.out.println("resultB: " + resultB);
Integer resultD = map.getOrDefault("D", 0);
System.out.println("resultD: " + resultD);
}
/* 测试结果
resultB: 2
resultD: 0
*/
forEach
遍历
// 源码
default void forEach(BiConsumer<? super K, ? super V> action) {
Objects.requireNonNull(action);
for (Map.Entry<K, V> entry : entrySet()) {
K k;
V v;
try {
k = entry.getKey();
v = entry.getValue();
} catch(IllegalStateException ise) {
// this usually means the entry is no longer in the map.
throw new ConcurrentModificationException(ise);
}
action.accept(k, v);
}
}
// 测试
@Test
public void forEach() {
Map<String, Integer> map = new HashMap<>();
map.put("A", 1);
map.put("B", 2);
map.put("C", 3);
// 我们以前使用Entry遍历
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + " -> " + entry.getValue());
}
// 现在forEach简单很多
map.forEach((key, value) -> {
System.out.println(key + " -> " + value);
});
}
replaceAll
按照指定的逻辑替换所有value
// 源码
default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
Objects.requireNonNull(function);
for (Map.Entry<K, V> entry : entrySet()) {
K k;
V v;
try {
k = entry.getKey();
v = entry.getValue();
} catch(IllegalStateException ise) {
// this usually means the entry is no longer in the map.
throw new ConcurrentModificationException(ise);
}
// ise thrown from function is not a cme.
v = function.apply(k, v);
try {
entry.setValue(v);
} catch(IllegalStateException ise) {
// this usually means the entry is no longer in the map.
throw new ConcurrentModificationException(ise);
}
}
}
// 测试
@Test
public void replaceAll() {
Map<String, Integer> map = new HashMap<>();
map.put("A", 1);
map.put("B", 2);
map.put("C", 3);
map.replaceAll((key, value) -> value + 10);
map.forEach((key, value) -> System.out.println(key + " -> " + value));
}
/* 测试结果
A -> 11
B -> 12
C -> 13
*/
putIfAbsent
缺少值时填充
// 源码
default V putIfAbsent(K key, V value) {
V v = get(key);
if (v == null) {
v = put(key, value);
}
return v;
}
// 测试
@Test
public void putIfAbsent() {
Map<String, Integer> map = new HashMap<>();
map.put("A", 1);
map.put("B", null);
map.putIfAbsent("A", 11);
map.putIfAbsent("B", 12);
map.putIfAbsent("C", 13);
map.forEach((key, value) -> System.out.println(key + " -> " + value));
}
/* 测试结果
A -> 1
B -> 12
C -> 13
*/
remove
键值对匹配时移除
// 源码
default boolean remove(Object key, Object value) {
Object curValue = get(key);
if (!Objects.equals(curValue, value) ||
(curValue == null && !containsKey(key))) {
return false;
}
remove(key);
return true;
}
// 测试
@Test
public void remove() {
Map<String, Integer> map = new HashMap<>();
map.put("A", 1);
map.put("B", 2);
map.put("C", 3);
map.remove("A", 1);
map.remove("B", 1);
map.forEach((key, value) -> System.out.println(key + " -> " + value));
}
/* 测试结果
B -> 2
C -> 3
*/
replace
存在或者匹配时进行替换
// 源码
default V replace(K key, V value) {
V curValue;
if (((curValue = get(key)) != null) || containsKey(key)) {
curValue = put(key, value);
}
return curValue;
}
default boolean replace(K key, V oldValue, V newValue) {
Object curValue = get(key);
if (!Objects.equals(curValue, oldValue) ||
(curValue == null && !containsKey(key))) {
return false;
}
put(key, newValue);
return true;
}
// 测试
@Test
public void replace() {
Map<String, Integer> map = new HashMap<>();
map.put("A", 1);
map.put("B", 1);
System.out.println("=== replace(K key, V value) ===");
map.replace("B", 2);
map.replace("C", 3);
map.forEach((key, value) -> System.out.println(key + " -> " + value));
System.out.println("=== replace(K key, V oldValue, V newValue) ===");
map.replace("A", 2, 11);
map.replace("B", 2, 12);
map.forEach((key, value) -> System.out.println(key + " -> " + value));
}
/* 测试结果
=== replace(K key, V value) ===
A -> 1
B -> 2
=== replace(K key, V oldValue, V newValue) ===
A -> 1
B -> 12
*/
computeIfAbsent
缺少值时写入计算结果
// 源码
default V computeIfAbsent(K key,
Function<? super K, ? extends V> mappingFunction) {
Objects.requireNonNull(mappingFunction);
V v;
if ((v = get(key)) == null) {
V newValue;
if ((newValue = mappingFunction.apply(key)) != null) {
put(key, newValue);
return newValue;
}
}
return v;
}
// 测试
@Test
public void computeIfAbsent() {
Map<Character, Integer> map = new HashMap<>();
map.put('A', 65);
map.put('B', 66);
map.put('C', null);
map.computeIfAbsent('C', (key) -> (int) key);
map.computeIfAbsent('D', (key) -> (int) key);
map.forEach((key, value) -> System.out.println(key + " -> " + value));
}
/* 测试结果
A -> 65
B -> 66
C -> 67
D -> 68
*/
computeIfPresent
存在时进行计算,使用计算值进行替换(计算值为null则移除)
// 源码
default V computeIfPresent(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
V oldValue;
if ((oldValue = get(key)) != null) {
V newValue = remappingFunction.apply(key, oldValue);
if (newValue != null) {
put(key, newValue);
return newValue;
} else {
remove(key);
return null;
}
} else {
return null;
}
}
// 测试
@Test
public void computeIfPresent() {
Map<Character, Integer> map = new HashMap<>();
map.put('A', 1);
map.put('B', 2);
map.put('C', null);
map.computeIfPresent('A', (key, oldValue) -> oldValue + 10);
map.computeIfPresent('B', (key, oldValue) -> null);
map.computeIfPresent('C', (key, oldValue) -> oldValue + 10);
map.forEach((key, value) -> System.out.println(key + " -> " + value));
}
/* 测试结果
A -> 11
C -> null
*/
compute
对指定key进行计算,添加计算值为value(计算值为null时移除)
// 源码
default V compute(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
V oldValue = get(key);
V newValue = remappingFunction.apply(key, oldValue);
if (newValue == null) {
// delete mapping
if (oldValue != null || containsKey(key)) {
// something to remove
remove(key);
return null;
} else {
// nothing to do. Leave things as they were.
return null;
}
} else {
// add or replace old mapping
put(key, newValue);
return newValue;
}
}
// 测试
@Test
public void compute() {
Map<Character, Integer> map = new HashMap<>();
map.put('A', 1);
map.put('B', 2);
map.compute('A', (key, oldValue) -> (int) key);
map.compute('B', (key, oldValue) -> null);
map.compute('C', (key, oldValue) -> (int) key);
map.forEach((key, value) -> System.out.println(key + " -> " + value));
}
/* 测试结果
A -> 65
C -> 67
*/
merge
合并旧值和新值
// 源码
default V merge(K key, V value,
BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
Objects.requireNonNull(value);
V oldValue = get(key);
V newValue = (oldValue == null) ? value :
remappingFunction.apply(oldValue, value);
if(newValue == null) {
remove(key);
} else {
put(key, newValue);
}
return newValue;
}
// 测试
@Test
public void merge() {
Map<Character, Integer> map = new HashMap<>();
map.put('A', 10);
map.put('B', 10);
map.merge('A', 1, (oldValue, value) -> oldValue + value);
map.merge('B', 2, (oldValue, value) -> oldValue + value);
map.merge('C', 3, (oldValue, value) -> oldValue + value);
map.forEach((key, value) -> System.out.println(key + " -> " + value));
}
/* 测试结果
A -> 11
B -> 12
C -> 3
*/