Map接口
双列集合,键值对(确保键的唯一)
构造函数
public interface Map<K,V>
内部接口 Entry
抽象了内部存储的节点,对应一个键值对
interface Entry<K,V> {
// 返回此项的Key
K getKey();
// 返回此项的value
V getValue();
// 设置此项的value
V setValue(V value);
/**
* 两个entry比较相等性
* (e1.getKey() == null ? e2.getKey() == null : e1.getKey().equals(e2.getKey())) &&
* (e1.getValue() == null ? e2.getValue() == null : e1.getValue().equals(e2.getValue()))
*/
boolean equals(Object o);
/**
* (e.getKey() == null ? 0 : e.getKey().hashCode()) ^
* (e.getValue() == null ? 0 : e.getValue().hashCode())
*/
int hashCode();
// 返回一个比较器 ,按键自然顺序比较Map.Entry
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());
}
// 返回一个比较器,比较Map.Entry的自然顺序值
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());
}
// 返回一个比较器,比较Map.Entry按键使用给定的Comparator
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());
}
// 返回一个比较器 ,使用给定的Comparator比较Map.Entry的值
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());
}
}
这里有出现个之前没见过的写法 (Comparator<Map.Entry<K, V>> & Serializable)
, &
我们知道是按位与的操作,那么两个对象之间使用呢?
对象强转为Comparator的同时也支持序列化
其实这个是java语法支持的强制类型转换表达式 ( ReferenceType & InterfaceType ) LambdaExpression
,也就是说Lambda表达式被转化为引用类型和接口类型两种类型
共性方法
// 返回键值对的数目,如果大于Integer.MAX_VALUE,则返回Integer.MAX_VALUE
int size();
// 如果map不包含键值对则返true
boolean isEmpty();
// 判断是否包含Key
boolean containsKey(Object key);
// 判断是否包含value
boolean containsValue(Object value);
// 返回到指定键所映射的值,如果不存在返回null(也可能是value就是null值)
V get(Object key);
// 将key和value进行关联,如果已存在key,则value将替换旧值并返回旧值,如果不存在key则返回null(也可能旧值就是null值)
V put(K key, V value);
// 如果key存在,则删除该key的映射,并返回value值,如果不存在返回null(也可能是value就是null值)
V remove(Object key);
// 将指定map中的键值对赋值到此map中
void putAll(Map<? extends K, ? extends V> m);
// 删除所有键值对
void clear();
// map的三视图之一,key的Set视图
Set<K> keySet();
// map的三视图之一,value的Collection视图
Collection<V> values();
// map的三视图之一,entry的Set视图
Set<Map.Entry<K, V>> entrySet();
jdk1.8新增的默认方法
// 获取指定key对应的value,如果指定key不存在则返回指定的默认vaule
default V getOrDefault(Object key, V defaultValue) {
V v;
return (((v = get(key)) != null) || containsKey(key)) ? v : defaultValue;
}
// 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);
}
}
// 将指定函数作用在所有key的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) {
throw new ConcurrentModificationException(ise);
}
v = function.apply(k, v);
try {
entry.setValue(v);
} catch(IllegalStateException ise) {
throw new ConcurrentModificationException(ise);
}
}
}
// 如果key存在并且对应的value并不为null则直接返回value,否则执行put操作
default V putIfAbsent(K key, V value) {
V v = get(key);
if (v == null) {
v = put(key, value);
}
return v;
}
// 根据key-value匹配删除,只有在key存在并且值相同时才执行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;
}
// 根据key-value匹配再替换旧值,只有key存在并且值相同时,才执行put操作
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匹配到了具体的键值对,才执行put操作并且返回旧值
default V replace(K key, V value) {
V curValue;
if (((curValue = get(key)) != null) || containsKey(key)) {
curValue = put(key, value);
}
return curValue;
}
// 根据key获取value,如果key不存在或者存在但是映射的value为null,则根据指定函数执行put操作返回新值
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存在,并且对应的value不为null,则根据指定函数执行put操作返回新值,否则返回null。
// 如果指定函数返回值为null,则代表删除该key
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是否存在都会执行put操作
// 如果指定函数返回值为null,则代表删除该key
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;
}
}
// 如果key不存在或者key存在但是value==null,执行put(key, value),否则执行put(key, function)
// 如果指定函数返回值为null,则代表删除该key
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;
}
示例
特别需要注意Key存在但是Value值为null的情况
Map<String, Integer> map = new HashMap<>(16);
map.put("s", 0);
map.put("s1", 1);
// getOrDefault 不会修改map数据
System.out.println(map.getOrDefault("s2", 2)); // return 2
System.out.println(map); // {s=0, s1=1}
// replaceAll
map.replaceAll((k, v) -> v * 2);
System.out.println(map); // {s=0, s1=2}
// putIfAbsent
// 1.key不存在,执行put("s2", null)
System.out.println(map.putIfAbsent("s2", null)); // return oldValue null
System.out.println(map); // {s=0, s1=2, s2=null}
// 2.key存在,value==null,执行put("s2", 100)
System.out.println(map.putIfAbsent("s2", 100)); // return oldValue null
System.out.println(map); // {s=0, s1=2, s2=100}
// 2.key存在,value!=null,什么都不做
System.out.println(map.putIfAbsent("s2", 200)); // return oldValue 100
System.out.println(map); // {s=0, s1=2, s2=100}
// remove(Object key, Object value)
// 1.key不存在,什么都不做
System.out.println(map.remove("s3", null)); // return false
// 2.key存在,但是value不匹配,什么都不做
System.out.println(map.remove("s2", 200)); // return false
// 3.key存在并且value匹配,执行remove("s2")
System.out.println(map.remove("s2", 100)); // return true
System.out.println(map); // {s=0, s1=2}
// replace(K key, V oldValue, V newValue)
// 1.key不存在,什么都不做
System.out.println(map.replace("s2", 200, 300)); // return false
// 2.key存在,oldValue不匹配,什么都不做
System.out.println(map.replace("s1", 200, 300)); // return false
// 3.key存在并且oldValue匹配,执行put("s1", null)
System.out.println(map.replace("s1", 2, null)); // return true
// 4.key存在并且oldValue匹配, value==null,执行put("s1, 400")
System.out.println(map.replace("s1", null, 400)); // return true
System.out.println(map); // {s=0, s1=400}
// replace(K key, V value)
// 1.key不存在,什么都不做
System.out.println(map.replace("s2", 200)); // return oldValue null
// 2.key存在,value!=null,执行put("s1", null)
System.out.println(map.replace("s1", null)); // return oldValue 400
// 3.key存在,value==null,执行put("s1", 500)
System.out.println(map.replace("s1", 500)); // return oldValue null
System.out.println(map); // {s=0, s1=500}
// computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)
Function<Integer, Integer> function = item -> item * 2;
// 1.key不存在,执行put("s2", 500 * 2)
System.out.println(map.computeIfAbsent("s2", k -> function.apply(500))); // return newValue 1000
// 2.key存在,value==null,执行put("s2", 600 * 2)
map.put("s2", null);
System.out.println(map.computeIfAbsent("s2", k -> function.apply(600))); // return newValue 1200
// 3.key存在,value!=null,什么都不做
System.out.println(map.computeIfAbsent("s2", k -> function.apply(700))); // return oldValue 1200
System.out.println(map); // {s=0, s1=500, s2=1200}
// computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)
// 1.key不存在,什么都不做
System.out.println(map.computeIfPresent("s3", (k, v) -> v * 3)); // return null
// 2.key存在,value==null,什么都不做
map.put("s2", null);
System.out.println(map.computeIfPresent("s2", (k, v) -> v * 3)); // return null
// 3.key存在,value!=null,执行put("s1", 500 * 3)
System.out.println(map.computeIfPresent("s1", (k, v) -> v * 3)); // return newValue 1500
// 4.key存在,value!=null,指定函数返回null,执行remove("s1")
System.out.println(map.computeIfPresent("s1", (k, v) -> null)); // return null
System.out.println(map); // {s=0, s2=null}
// compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)
// 1.key不存在,执行put("s1", 0)
System.out.println(map.compute("s1", (k, v) -> {
if (v == null) return 0;
return v + 1;
})); // return newValue 0
// 2.key存在,value==null,执行put("s2", 0)
System.out.println(map.compute("s2", (k, v) -> {
if (v == null) return 0;
return v + 1;
})); // return newValue 0
// 3.key存在,value!=null,执行put("s2", 1)
System.out.println(map.compute("s2", (k, v) -> {
if (v == null) return 0;
return v + 1;
})); // return newValue 1
// 4.key存在,指定函数返回null,执行remove("s2")
System.out.println(map.compute("s2", (k, v) -> null)); // return null
System.out.println(map); // {s=0, s1=0}
// merge
// 1.key不存在,执行put("s2", 1)
System.out.println(map.merge("s2", 1, (k, v) -> v + 1)); // return newValue 1
// 2.key存在,value!=null,执行put("s2", 1 + 1)
System.out.println(map.merge("s2", 1, (k, v) -> v + 1)); // return newValue 2
// 3.key存在,value==null,执行put("s2", 1)
map.put("s2", null);
System.out.println(map.merge("s2", 1, (k, v) -> v + 1)); // return newValue 1
// 4.指定函数返回null,则执行remove("s2")
System.out.println(map.merge("s2", 1, (k, v) -> null)); // return get(key) == null ? value : function
System.out.println(map); // {s=0, s1=0}