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}