Java 8 Map 新增方法详解
Java 8 Map 新增方法详解
1. getOrDefault
源码:
default V getOrDefault(Object key, V defaultValue) {V v;return (((v = get(key)) != null) || containsKey(key))? v: defaultValue;}
作用:安全获取值,若key不存在则返回默认值
示例:
Map<String, Integer> scores = new HashMap<>();
scores.put("Alice", 90);
System.out.println(scores.getOrDefault("Bob", 0)); // 输出 0
2. 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);}}
作用:遍历Map的所有键值对
示例:
Map<String, Integer> map = Map.of("A", 1, "B", 2);
map.forEach((k, v) -> System.out.println(k + ":" + v));
// 输出:
// A:1
// B:2
3. replaceAll
源码:
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);}}}
作用:替换所有值(基于键值对的函数计算)
示例:
Map<String, Integer> map = new HashMap<>();
map.put("A", 1); map.put("B", 2);
map.replaceAll((k, v) -> v * 10);
System.out.println(map); // 输出 {A=10, B=20}
4. putIfAbsent
源码:
default V putIfAbsent(K key, V value) {V v = get(key);if (v == null) {v = put(key, value);}return v;}
作用:仅当key不存在时插入值
示例:
Map<String, Integer> map = new HashMap<>();
map.put("A", 1);
map.putIfAbsent("A", 100); // 无效
map.putIfAbsent("B", 2); // 成功
System.out.println(map); // 输出 {A=1, B=2}
5. 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;}
作用:仅当键值匹配时才删除
示例:
Map<String, String> map = new HashMap<>();
map.put("lang", "Java");
map.remove("lang", "Python"); // 失败
map.remove("lang", "Java"); // 成功
6. replace (条件替换)
源码:
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;}
作用:仅当旧值匹配时才替换
示例:
Map<String, String> map = new HashMap<>();
map.put("lang", "Java");
map.replace("lang", "C++", "Rust"); // 失败
map.replace("lang", "Java", "Go"); // 成功
7. replace (无条件替换)
源码:
default V replace(K key, V value) {V curValue;if (((curValue = get(key)) != null) || containsKey(key)) {curValue = put(key, value);}return curValue;}
作用:替换存在的key的值
示例:
Map<String, String> map = new HashMap<>();
map.put("lang", "Java");
map.replace("lang", "Go"); // 成功
map.replace("os", "Linux"); // 无效果
8. 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;}
作用:key不存在时通过函数生成值
示例:
Map<String, List<String>> map = new HashMap<>();
map.computeIfAbsent("fruits", k -> new ArrayList<>()).add("Apple");
System.out.println(map); // 输出 {fruits=[Apple]}
springboot源码中的:
public static SpringFactoriesLoader forResourceLocation(String resourceLocation, @Nullable ClassLoader classLoader) {Assert.hasText(resourceLocation, "'resourceLocation' must not be empty");ClassLoader resourceClassLoader = (classLoader != null ? classLoader :SpringFactoriesLoader.class.getClassLoader());Map<String, SpringFactoriesLoader> loaders = cache.computeIfAbsent(resourceClassLoader, key -> new ConcurrentReferenceHashMap<>());return loaders.computeIfAbsent(resourceLocation, key ->new SpringFactoriesLoader(classLoader, loadFactoriesResource(resourceClassLoader, resourceLocation)));}
说明:
cache
类型为ConcurrentReferenceHashMap
static final Map<ClassLoader, Map<String, SpringFactoriesLoader>> cache = new ConcurrentReferenceHashMap<>();
使用computeIfAbsent
,查看有没有以resourceClassLoader
为key的值,如果没有,则new
一个ConcurrentReferenceHashMap
给loaders
Map<String, SpringFactoriesLoader> loaders = cache.computeIfAbsent(resourceClassLoader, key -> new ConcurrentReferenceHashMap<>());
接着看loaders
中有没有以resourceLocation
为key
的值,没有的话,则new
一个SpringFactoriesLoader
并返回
9. computeIfPresent
源码:
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;}}
作用:key存在时通过函数计算新值
示例:
Map<String, Integer> map = new HashMap<>();
map.put("count", 5);
map.computeIfPresent("count", (k, v) -> v * 2); // 变为10
map.computeIfPresent("total", (k, v) -> v + 1); // 无变化
10. compute
源码:
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 mappingif (oldValue != null || containsKey(key)) {// something to removeremove(key);return null;} else {// nothing to do. Leave things as they were.return null;}} else {// add or replace old mappingput(key, newValue);return newValue;}}
作用:动态计算键的新值(处理存在/不存在情况)
示例:
Map<String, Integer> map = new HashMap<>();
map.put("a", 2);
map.compute("a", (k, v) -> v == null ? 0 : v + 1); // a=3
map.compute("b", (k, v) -> v == null ? 0 : v + 1); // b=0
11. 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;}
作用:合并键值(处理null值)
示例:
Map<String, String> map = new HashMap<>();
map.put("lang", "Java");
map.merge("lang", "Script", (oldV, newV) -> oldV + newV); // JavaScript
map.merge("new", "Key", (oldV, newV) -> oldV + newV); // Key
12. of (创建不可变Map,这是一个重载的方法)
源码:
static <K, V> Map<K, V> of() {return (Map<K,V>) ImmutableCollections.EMPTY_MAP;}
作用:创建0-10个元素的不可变Map
示例:
Map<String, Integer> empty = Map.of();
Map<String, Integer> single = Map.of("a", 1);
Map<String, Integer> multiple = Map.of("a", 1, "b", 2);
// 尝试修改会抛 UnsupportedOperationException
13. ofEntries
源码:
static <K, V> Map<K, V> ofEntries(Entry<? extends K, ? extends V>... entries) {if (entries.length == 0) { // implicit null check of entries array@SuppressWarnings("unchecked")var map = (Map<K,V>) ImmutableCollections.EMPTY_MAP;return map;} else if (entries.length == 1) {// implicit null check of the array slotreturn new ImmutableCollections.Map1<>(entries[0].getKey(),entries[0].getValue());} else {Object[] kva = new Object[entries.length << 1];int a = 0;for (Entry<? extends K, ? extends V> entry : entries) {// implicit null checks of each array slotkva[a++] = entry.getKey();kva[a++] = entry.getValue();}return new ImmutableCollections.MapN<>(kva);}}
作用:通过Entry对象创建不可变Map
示例:
Map.Entry<String, Integer> e1 = Map.entry("a", 1);
Map.Entry<String, Integer> e2 = Map.entry("b", 2);
Map<String, Integer> map = Map.ofEntries(e1, e2);
14. entry
源码:
static <K, V> Entry<K, V> entry(K k, V v) {// KeyValueHolder checks for nullsreturn new KeyValueHolder<>(k, v);}
作用:创建键值对Entry对象
示例:
Map.Entry<String, Integer> entry = Map.entry("key", 100);
System.out.println(entry.getKey() + ":" + entry.getValue());
15. copyOf
源码:
static <K, V> Map<K, V> copyOf(Map<? extends K, ? extends V> map) {if (map instanceof ImmutableCollections.AbstractImmutableMap) {return (Map<K,V>)map;} else {return (Map<K,V>)Map.ofEntries(map.entrySet().toArray(new Entry[0]));}}
作用:创建Map的不可变副本
示例:
Map<String, Integer> original = new HashMap<>();
original.put("a", 1);
Map<String, Integer> copy = Map.copyOf(original);
// 修改original不影响copy