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