前言
本文章帮助大家对Map
接口的理解。
一、概述
Map
意为映射。顾名思义,此类可以将键和值映射起来,是同一类“键值对”(元素)的“集合”(非Collection
,参考Collection
接口),类似Dictionary
抽象类,但后者比较局限,不推荐使用,参考Dictionary
抽象类。其不能包含相同的键,一个键最多只能映射一个值。要使用键值对功能的话,推荐使用此接口。
其虽非Collection
,但对键、值、键值对的集合提供集合视图。元素顺序由其对应集合视图的迭代器定义。
of
、ofEntries
、copyOf
静态方法可以创建不可修改的映射容器(下简称“映射”),即不能增加、删除、修改其元素。但若元素本身是可修改的,其修改会导致不一致的行为。其键、值均不能为空。其迭代顺序是不确定的。
二、源码理解
包
package java.util;
import java.util.Map;
使用Map
接口时,需引入此包。
Map接口
public interface Map<K, V> { /*...*/ }
使用接口时传入泛型K
、V
,为键、值的类型。
注意:若元素的键是可修改对象,其修改会导致不确定的行为,其中一种情况就是将其实现类对象作为其元素的键。其实现类对象不能作为其元素的值,否则导致其equals
和hashCode
等方法不能很好地定义。很多方法需要用到equals
和hashCode
方法。
注意:要求其实现类遵守如此规定:需实现两个构造函数:一个无参数构造函数,以创建一个空映射;一个参数为Map
类型的构造函数,以创建一个具有和参数相同元素的映射。但由于接口不能包含构造函数,所以无法强制执行此规定。
但Java平台库中的所有通用映射实现都符合此约定。
Entry
Entry
意为项。顾名思义,它提供映射的项的结构(这里称该映射为其“支持映射”)。
interface Entry<K, V> { /*...*/ }
使用接口时传入泛型K
、V
,为键、值的类型。
重点:若想要实现类是不可修改的,那么应该不实现其setValue
方法。
Entry方法
getKey
K getKey();
返回键。若此项已从其支持映射删除,可抛出IllegalStateException
异常。
getValue
V getValue();
返回值。若此项已从其支持映射删除,可抛出IllegalStateException
异常。
setValue
V setValue(V value);
设置值,返回原值(可选)。
若其支持映射不支持put
方法,则抛出UnsupportedOperationException
异常;若因value
的类而不能加入其支持映射中,则抛出ClassCastException
异常;若value
为空而其支持映射不允许有空值,则抛出NullPointerException
异常;若因value
的一些属性而不能加入其支持映射中,则抛出IllegalArgumentException
异常;若此项已从其支持映射删除,可抛出IllegalStateException
异常。
equals
boolean equals(Object o);
重写Object
类的boolean equals(Object obj)
方法,参考Object.equals
方法。
判断此项与o
的键值对是否相等。相等的条件为:o
也实现了项接口且它们键、值均相等(equals
)。
hashCode
int hashCode();
重写Object
类的int hashCode()
方法,参考Object.hashCode
方法。
返回此项键、值的哈希码的异或。
comparingByKey
public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K, V>> comparingByKey() {
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> c1.getKey().compareTo(c2.getKey());
}
静态方法,传入泛型K
、V
,为比较项的键、值类型,K
继承Comparable<? super K>
接口,需要是可比较的(即自身带有Comparable.compareTo
方法)。返回比较项的比较器(实现Serializable
接口)的比较结果同键的自然序比较结果。参考Comparator
接口、Serializable
接口、Comparable
接口。
若返回比较器中出现异常,那么这些异常会交给返回比较器的调用方处理。
public static <K, V> Comparator<Map.Entry<K, V>> comparingByKey(Comparator<? super K> cmp) {
Objects.requireNonNull(cmp);
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> cmp.compare(c1.getKey(), c2.getKey());
}
静态方法,传入泛型K
、V
,为比较项的键、值类型。返回比较项的比较器(实现Serializable
接口)的比较结果同键的cmp
比较器的比较结果。参考Comparator
接口、Serializable
接口。
若cmp
为空,则抛出NullPointerException
异常。参考Objects.requireNonNull
方法。
若返回比较器中出现异常,那么这些异常会交给返回比较器的调用方处理。
comparingByValue
public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K, V>> comparingByValue() {
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> c1.getValue().compareTo(c2.getValue());
}
静态方法,传入泛型K
、V
,为比较项的键、值类型,V
继承Comparable<? super V>
接口,需要是可比较的(即自身带有Comparable.compareTo
方法)。返回比较项的比较器(实现Serializable
接口)的比较结果同值的自然序比较结果。参考Comparator
接口、Serializable
接口、Comparable
接口。
若返回比较器中出现异常,那么这些异常会交给返回比较器的调用方处理。
public static <K, V> Comparator<Map.Entry<K, V>> comparingByValue(Comparator<? super V> cmp) {
Objects.requireNonNull(cmp);
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> cmp.compare(c1.getValue(), c2.getValue());
}
静态方法,传入泛型K
、V
,为比较项的键、值类型。返回比较项的比较器(实现Serializable
接口)的比较结果同值的cmp
比较器的比较结果。参考Comparator
接口、Serializable
接口。
若cmp
为空,则抛出NullPointerException
异常。参考Objects.requireNonNull
方法。
若返回比较器中出现异常,那么这些异常会交给返回比较器的调用方处理。
copyOf
public static <K, V> Map.Entry<K, V> copyOf(Map.Entry<? extends K, ? extends V> e) {
Objects.requireNonNull(e);
if (e instanceof KeyValueHolder) {
return (Map.Entry<K, V>) e;
} else {
return Map.entry(e.getKey(), e.getValue());
}
}
静态方法,传入泛型K
、V
,为返回项的键、值类型。返回键值同e
的不可修改项。若e
中存在为空的键或值,或e
为空,则抛出NullPointerException
异常。
注意:返回项通常是项参数的复制。
Map方法
size
int size();
返回元素个数。若映射包含元素个数大于Integer.MAX_VALUE
,则返回Integer.MAX_VALUE
。
isEmpty
boolean isEmpty();
判断映射是否为空。
equals
boolean equals(Object o);
重写Object
类的boolean equals(Object obj)
方法,参考Object.equals
方法。
判断此映射和对象o
是否相同/相等。通常要返回true
需要它们的项集相等。
hashCode
int hashCode();
重写Object
类的int hashCode()
方法,参考Object.hashCode
方法。
返回此映射的哈希码。它定义为项集视图里所有项的哈希码的和(不同实现不一定是返回其和)。
containsKey
boolean containsKey(Object key);
判断映射是否包含键为对象key
的项。通常认为找到一个键k
,存在Objects.equals(key, k)
则返回true
。
若对象key
的类型和键类型不能比较,则抛出ClassCastException
异常(可选);若对象key
为空而映射不允许有空键,则抛出NullPointerException
异常(可选)。
containsValue
boolean containsValue(Object value);
判断映射是否包含值为对象value
的项。通常认为找到一个值v
,存在Objects.equals(value, v)
则返回true
。
若对象value
的类型和键类型不能比较,则抛出ClassCastException
异常(可选);若对象value
为空而映射不允许有空值,则抛出NullPointerException
异常(可选)。
大多实现要求此查询时间对于元素数量是线性的。
get
V get(Object key);
返回键为key
的值。若查无键key
,则返回空。通常认为找到一个键k
,存在Objects.equals(key, k)
则返回其值。
若对象key
的类型和键类型不能比较,则抛出ClassCastException
异常(可选);若对象key
为空而映射不允许有空键,则抛出NullPointerException
异常(可选)。
注意:返回空值不一定因为查无键key
,有可能此映射允许值为空且查询到的值为空。可通过containsKey
方法来区分这两种情况。
getOrDefault
default V getOrDefault(Object key, V defaultValue) { /*...*/ }
返回键为key
的值。若查无键key
,则返回defaultValue
。default
关键字给出默认实现。
若对象key
的类型和键类型不能比较,则抛出ClassCastException
异常(可选);若对象key
为空而映射不允许有空键,则抛出NullPointerException
异常(可选)。
注意:查到值为空,也应返回空。
put
V put(K key, V value);
将键为key
的值替换为value
,并返回原来的值(可选)。若查无键key
,则新增此键值对,返回空。
若实现类不支持put
方法,则抛出UnsupportedOperationException
异常;若因key
或value
的类而不能加入映射中,则抛出ClassCastException
异常;若key
或value
为空而映射不允许有空键或值,则抛出NullPointerException
异常;若因key
或value
的一些属性而不能加入映射中,则抛出IllegalArgumentException
异常。
注意:返回空值不一定因为查无键key
,有可能此映射允许值为空且查询到的值为空。可通过containsKey
方法来区分这两种情况。
putIfAbsent
default V putIfAbsent(K key, V value) {
V v = get(key);
if (v == null) {
v = put(key, value);
}
return v;
}
将键为key
的不存在值的值替换为value
。若查无键key
,则新增此键值对,返回空;若查到值为空,则将其替换为value
,返回空;否则不新增并返回原来的值。default
关键字给出默认实现。
若实现类不支持put
方法,则抛出UnsupportedOperationException
异常(可选);若key
或value
的类型和此映射键或值的类型不能比较,则抛出ClassCastException
异常(可选);若key
或value
为空而映射不允许有空键或值,则抛出NullPointerException
异常(可选);若因key
或value
的一些属性而不能加入映射中,则抛出IllegalArgumentException
异常(可选)。
注意:返回空值不一定因为查无键key
,有可能此映射允许值为空且查询到的值为空,但结果都是新键值对存入映射中。可通过containsKey
方法来区分这两种情况。
putAll
void putAll(Map<? extends K, ? extends V> m);
添加映射m
的所有元素到此映射中(可选)。相当于对m
中所有键值对进行一遍put
操作。在此操作过程中,若修改此映射,那么此操作将出现为定义行为。
若实现类不支持putAll
操作,则抛出UnsupportedOperationException
异常;若因m
中某键或值的类而不能加入此映射中,则抛出ClassCastException
异常;若m
中某键或值为空而此映射不允许有空键或值,或m
为空,则抛出NullPointerException
异常;若因m
中某键或值的一些属性而不能加入此映射中,则抛出IllegalArgumentException
异常。
remove
V remove(Object key);
从映射中移除键为key
的元素,并返回原来的值(若有的话),若查无键key
,则返回空(可选)。通常认为找到一个键k
,存在Objects.equals(key, k)
则移除。若成功移除,返回true
。
若实现类不支持remove
操作,则抛出UnsupportedOperationException
异常;若对象key
的类型和键类型不能比较,则抛出ClassCastException
异常(可选);若对象key
为空而映射不允许有空键,则抛出NullPointerException
异常(可选)。
注意:返回空值不一定因为查无键key
,有可能此映射允许值为空且查询到的值为空。可通过containsKey
方法来区分这两种情况。
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;
}
从映射中移除键为key
、值为value
的元素,若成功移除,返回true
。default
关键字给出默认实现。
若实现类不支持remove
操作,则抛出UnsupportedOperationException
异常(可选);若对象key
、value
的类型和键、值类型不能比较,则抛出ClassCastException
异常(可选);若对象key
或value
为空而映射不允许有空键或值,则抛出NullPointerException
异常(可选)。
注意:即使查到值为空,也要移除并返回true
。
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;
}
将映射中键为key
、值为oldValue
的项的值替换为newValue
,若成功替换,返回true
。default
关键字给出默认实现。
若实现类不支持put
操作,则抛出UnsupportedOperationException
异常(可选);若因替换键或值的类而不能加入此映射中,则抛出ClassCastException
异常;若对象key
或newValue
为空而映射不允许有空键或值,或oldValue
为空而映射不允许有空值(可选),则抛出NullPointerException
异常;若因替换键或值的一些属性而不能加入此映射中,则抛出IllegalArgumentException
异常。
注意:即使查到值为空,也要替换并返回true
。
default V replace(K key, V value) {
V curValue;
if (((curValue = get(key)) != null) || containsKey(key)) {
curValue = put(key, value);
}
return curValue;
}
将映射中键为key
的项的值替换为value
,若成功替换,返回原值,否则返回空。default
关键字给出默认实现。
若实现类不支持put
操作,则抛出UnsupportedOperationException
异常(可选);若因替换键或值的类而不能加入此映射中,则抛出ClassCastException
异常(可选);若对象key
或value
为空而映射不允许有空键或值,则抛出NullPointerException
异常;若因替换键或值的一些属性而不能加入此映射中,则抛出IllegalArgumentException
异常。
注意:只要查到键,就要替换。
replaceAll
default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) { /*...*/ }
替换此映射中的各个值,替换规则由二元函数式function
给定,参考BiFunction
接口。default
关键字给出默认实现,实现中用项集的迭代器遍历每个键和值,用function
的apply
方法转化设置元素。
若function
函数式返回空而此映射不允许有空值(可选),或function
为空,则抛出NullPointerException
异常;若此映射不可修改,或项集的迭代器不支持set
方法,则抛出UnsupportedOperationException
异常;若替换值的类型和此映射值类型不能比较(可选),或因替换值的类而不能加入此映射中,则抛出ClassCastException
异常;若因替换值的一些属性而不能加入此映射中,则抛出IllegalArgumentException
异常(可选);若遍历过程中有项被移除,则抛出ConcurrentModificationException
异常。
computeIfAbsent
default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) { /*...*/ }
将键为key
的不存在值的值替换为mappingFunction
的计算结果。若查无键key
或查到值为空,若key
经mappingFunction
函数式计算结果为空,不处理并返回空,否则设键key
值为计算结果并返回新值;若查键key
值非空,不处理并返回原值。default
关键字给出默认实现。
若实现类不支持put
方法,则抛出UnsupportedOperationException
异常(可选);若key
或value
的类型和此映射键或值的类型不能比较,则抛出ClassCastException
异常(可选);若key
或value
为空而映射不允许有空键或值,则抛出NullPointerException
异常(可选);若因key
或value
的一些属性而不能加入映射中,则抛出IllegalArgumentException
异常(可选)。
注意:默认实现没有检测mappingFunction
计算过程有没修改此映射,非并发实现 应在检测到其修改映射时抛出ConcurrentModificationException
异常,并发实现应在检测到其修改映射时抛出IllegalStateException
异常。
computeIfPresent
default V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) { /*...*/ }
将键为key
的存在值的值替换为remappingFunction
的计算结果。若查键key
值非空,若key
、原值经remappingFunction
二元函数式计算结果为空,移除此键并返回空,否则设键key
值为计算结果并返回新值;若查无键key
或查到值为空,不处理并返回空。default
关键字给出默认实现。
若实现类不支持put
方法,则抛出UnsupportedOperationException
异常(可选);若因key
或计算结果的类而不能加入映射中,则抛出ClassCastException
异常(可选);若key
为空而映射不允许有空键,或remappingFunction
为空,则抛出NullPointerException
异常;若因key
或计算结果的一些属性而不能加入映射中,则抛出IllegalArgumentException
异常(可选)。
注意:默认实现没有检测remappingFunction
计算过程有没修改此映射,非并发实现 应在检测到其修改映射时抛出ConcurrentModificationException
异常,并发实现应在检测到其修改映射时抛出IllegalStateException
异常。
compute
default V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) { /*...*/ }
将键为key
的值替换为remappingFunction
的计算结果。若key
、原值(或空)经remappingFunction
二元函数式计算结果为空,若查有此键,移除此键并返回空,否则返回空;若计算结果非空,设键key
值为计算结果并返回新值。default
关键字给出默认实现。
若实现类不支持put
方法,则抛出UnsupportedOperationException
异常(可选);若因key
或计算结果的类而不能加入映射中,则抛出ClassCastException
异常(可选);若key
为空而映射不允许有空键,或remappingFunction
为空,则抛出NullPointerException
异常;若因key
或计算结果的一些属性而不能加入映射中,则抛出IllegalArgumentException
异常(可选)。
注意:默认实现没有检测remappingFunction
计算过程有没修改此映射,非并发实现 应在检测到其修改映射时抛出ConcurrentModificationException
异常,并发实现应在检测到其修改映射时抛出IllegalStateException
异常。
merge
default V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) { /*...*/ }
将键为key
的值与value
合并。若查无键key
或查到值为空,则新值为value
,否则新值为原值、value
经remappingFunction
二元函数式计算结果。若新值为空,移除此键并返回空;否则设键key
值为计算结果并返回新值。default
关键字给出默认实现。
若实现类不支持put
方法,则抛出UnsupportedOperationException
异常(可选);若因key
或计算结果的类而不能加入映射中,则抛出ClassCastException
异常(可选);若key
为空而映射不允许有空键,或value
或remappingFunction
为空,则抛出NullPointerException
异常;若因key
或计算结果的一些属性而不能加入映射中,则抛出IllegalArgumentException
异常(可选)。
注意:默认实现没有检测remappingFunction
计算过程有没修改此映射,非并发实现 应在检测到其修改映射时抛出ConcurrentModificationException
异常,并发实现应在检测到其修改映射时抛出IllegalStateException
异常。
clear
void clear();
清空此映射(可选)。若实现类不支持clear
操作,则抛出UnsupportedOperationException
异常。
keySet
Set<K> keySet();
返回此映射的所有键的Set
集合视图。参考Set
接口。
重点:返回集合受此映射支撑,对返回集合的非结构修改也会反映到此映射上,反之亦然。
注意:返回视图及其迭代器的删除操作可删除映射中对应键的项,但不支持添加操作。若在迭代遍历时映射进行修改操作,将导致不确定的行为。
values
Collection<V> values();
返回此映射的所有值的Collection
集合视图。参考Collection
接口。
重点:返回集合受此映射支撑,对返回集合的非结构修改也会反映到此映射上,反之亦然。
注意:返回视图及其迭代器的删除操作可删除映射中对应值的项,但不支持添加操作。若在迭代遍历时映射进行修改操作,将导致不确定的行为。
entrySet
Set<Map.Entry<K, V>> entrySet();
返回此映射的所有项的Set
集合视图。
重点:返回集合受此映射支撑,对返回集合的非结构修改也会反映到此映射上,反之亦然。
注意:返回视图及其迭代器的删除操作可删除映射中对应项,但不支持添加操作。若在迭代遍历时映射进行修改操作,将导致不确定的行为。
forEach
default void forEach(BiConsumer<? super K, ? super V> action) { /*...*/ }
遍历所有元素的键和值(遍历顺序为项集的迭代顺序),对其调用action
。参考BiConsumer
接口。default
关键字给出默认实现。
若参数为空,则抛出NullPointerException
异常;若遍历过程中有项被移除,则抛出ConcurrentModificationException
异常。
of
static <K, V> Map<K, V> of() {
return (Map<K,V>) ImmutableCollections.EMPTY_MAP;
}
静态方法,传入泛型K
、V
,为返回映射的键、值类型。返回不包含元素的不可修改映射。参考ImmutableCollections
类。
static <K, V> Map<K, V> of(K k1, V v1) {
return new ImmutableCollections.Map1<>(k1, v1);
}
静态方法,传入泛型K
、V
,为返回映射的键、值类型。返回包含参数元素的不可修改映射。若存在为空的参数,则抛出NullPointerException
异常。
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2) {
return new ImmutableCollections.MapN<>(k1, v1, k2, v2);
}
静态方法,传入泛型K
、V
,为返回映射的键、值类型。返回包含参数元素的不可修改映射。类似of(K k1, V v1)
方法,若键有重复值,则抛出IllegalArgumentException
异常。
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3);
}
静态方法,传入泛型K
、V
,为返回映射的键、值类型。返回包含参数元素的不可修改映射。类似of(K k1, V v1)
方法,若键有重复值,则抛出IllegalArgumentException
异常。
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4);
}
静态方法,传入泛型K
、V
,为返回映射的键、值类型。返回包含参数元素的不可修改映射。类似of(K k1, V v1)
方法,若键有重复值,则抛出IllegalArgumentException
异常。
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5);
}
静态方法,传入泛型K
、V
,为返回映射的键、值类型。返回包含参数元素的不可修改映射。类似of(K k1, V v1)
方法,若键有重复值,则抛出IllegalArgumentException
异常。
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
K k6, V v6) {
return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5,
k6, v6);
}
静态方法,传入泛型K
、V
,为返回映射的键、值类型。返回包含参数元素的不可修改映射。类似of(K k1, V v1)
方法,若键有重复值,则抛出IllegalArgumentException
异常。
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
K k6, V v6, K k7, V v7) {
return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5,
k6, v6, k7, v7);
}
静态方法,传入泛型K
、V
,为返回映射的键、值类型。返回包含参数元素的不可修改映射。类似of(K k1, V v1)
方法,若键有重复值,则抛出IllegalArgumentException
异常。
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
K k6, V v6, K k7, V v7, K k8, V v8) {
return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5,
k6, v6, k7, v7, k8, v8);
}
静态方法,传入泛型K
、V
,为返回映射的键、值类型。返回包含参数元素的不可修改映射。类似of(K k1, V v1)
方法,若键有重复值,则抛出IllegalArgumentException
异常。
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9) {
return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5,
k6, v6, k7, v7, k8, v8, k9, v9);
}
静态方法,传入泛型K
、V
,为返回映射的键、值类型。返回包含参数元素的不可修改映射。类似of(K k1, V v1)
方法,若键有重复值,则抛出IllegalArgumentException
异常。
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10) {
return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5,
k6, v6, k7, v7, k8, v8, k9, v9, k10, v10);
}
静态方法,传入泛型K
、V
,为返回映射的键、值类型。返回包含参数元素的不可修改映射。类似of(K k1, V v1)
方法,若键有重复值,则抛出IllegalArgumentException
异常。
ofEntries
static <K, V> Map<K, V> ofEntries(Entry<? extends K, ? extends V>... entries) { /*...*/ }
静态方法,传入泛型K
、V
,为返回映射的键、值类型。返回包含参数元素的不可修改映射。若存在为空的参数(包括其键、值),或数组参数为空,则抛出NullPointerException
异常,若参数有重复键,则抛出IllegalArgumentException
异常。
注意:此方法与of
方法参数不同,此方法参数为项数组,非数个键和值。
entry
static <K, V> Entry<K, V> entry(K k, V v) {
return new KeyValueHolder<>(k, v);
}
静态方法,传入泛型K
、V
,为返回项的键、值类型。返回键、值为参数的不可修改项。若存在为空的参数,则抛出NullPointerException
异常。参考KeyValueHolder
类。
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]));
}
}
静态方法,传入泛型K
、V
,为返回映射的键、值类型。返回包含映射map
的所有元素的不可修改映射。若映射map
中存在为空的键或值,或映射map
为空,则抛出NullPointerException
异常。
注意:返回映射通常是映射参数的复制(使用了Set.toArray
进行复制,使用了ofEntries
方法包含非空检验。参考Set.toArray
方法),原映射修改不会影响到返回映射,但如果参数映射是不可修改映射,那么返回映射通常不是它的复制(即返回参数本身(本就有非空检验))。
总结
新人源码理解,望大家多多指点。