文章首發(fā)csdn博客地址:https://blog.csdn.net/u013277209?viewmode=contents
Map接口分析
關(guān)于Map接口谴返,JDK是這樣描述的:
- Map是一個有鍵值對映射的對象嫉到,map不能包含相同的key,每一個key至多能映射一個value。
- Map替代了Dictionary這個類,Dictionary是抽象類而非接口,替代原因:接口總是優(yōu)于抽象類锅纺。
- Map接口提供了3個集合視圖,包括:keys的set集合肋殴, values的集合;囤锉,key-value的set集合坦弟,注意:values集合不是set類型,因為value可相同。
- Map返回元素的順序官地,取決于map對應(yīng)的某個集合視圖迭代器的順序酿傍,一些map的實現(xiàn),比如TreeMap類驱入,對于map返回元素的順序有特殊的規(guī)定赤炒,其它的map實現(xiàn)類,比如HashMap類,就沒有特殊的規(guī)定。
- 不要把異變的對象作為Map的key亏较,如果map中的一個key發(fā)生了改變莺褒,并且影響了equals()方法的使用,那么map并不會提示我們雪情。
- 所有的通用map實現(xiàn)類都應(yīng)該提供兩個"標準"的構(gòu)造器函數(shù)遵岩,一個是無參且返回類型為void的函數(shù),另一個就是僅含有一個參數(shù)且類型為map類型的的構(gòu)造方法,這個方法會使用其參數(shù)構(gòu)造一個新的map巡通,且新的map和參數(shù)map有相同的key和value尘执,但是,map接口這里沒辦法強制執(zhí)行這一建議(因為接口里面不能包含構(gòu)造器函數(shù))宴凉,不過JDK里面所有通用的map實現(xiàn)類都是符合這一點要求的誊锭。
- 一些map的實現(xiàn)類在key和value的取值上面會有一些規(guī)定,比如弥锄,一些map實現(xiàn)類不允許key或者value為null丧靡。
- map接口是java集合框架中的一個成員。
- 集合框架接口定義了很多種和equals()方法相關(guān)的實現(xiàn)籽暇,比如,containsKey()方法窘行,當前僅當map包含了鍵k的定義是:key = = null ? k == null : key.equals(k),這一規(guī)范的寫法图仓,不能被理解為為:如果調(diào)用方法使用的是一個非null參數(shù)的話,然后只是再調(diào)用key.equals(k)方法就可以了罐盔,具體實現(xiàn)可以通過避免調(diào)用equals()方法來實現(xiàn)優(yōu)化,比如救崔,可以先比較兩個key的哈希值惶看,(哈希值保證了,如果兩個對象的哈希值都不相同六孵,那么這兩個對象肯定不會相同)纬黎,更一般的情況是,大量集合框架接口的實現(xiàn)類可以充分利用底層對象(Object)的方法的優(yōu)勢劫窒,只要實現(xiàn)者認為他們這么做是合理的本今。
public interface Map<K,V> {
//增
/**
* put方法是將指定的key-value存儲到map里面的操作.如果map之前包含了一個此key對應(yīng)的映射,
* 那么此key對應(yīng)的舊value值會被新的value值替換.
*/
V put(K key, V value);
/**
* putAll方法是將一個指定map的映射拷貝到當前map.這一操作類似于將指定map的key-value對通過put方法一個個拷貝過來。
* 在拷貝過程中,如果指定的這個map被更改了,那么這時候會出現(xiàn)什么情況,并不清楚。
*/
void putAll(Map<? extends K, ? extends V> m);
//刪
/**
* remove方法用于移除map中已有的某個key.更一般的講,如果map包含了一個滿足條件key==null ? k==null : key.equals(k)的映射,
* 這一映射就會被移除.(map最多包含一個這樣的映射)
* 本方法會返回移除的key對應(yīng)的value值,如果map這個key沒有對應(yīng)的value值,則返回null冠息。
* 如果map允許null值,那么返回null值并不一定表明map不包含對應(yīng)key的映射值;因為這也可能是key本身對應(yīng)的value值就是null.
*/
V remove(Object key);
/**
* 移除map中所有的映射
*/
void clear();
//查
/**
* 返回map中key-value映射的個數(shù).如果map包含的key-value個數(shù)超過了Integer.MAX_VALUE這個數(shù)
* 則返回Integer.MAX_VALUE.
*/
int size();
/**
* 如果map沒有存儲任何key-value,則返回true
*/
boolean isEmpty();
/**
* 如果map存儲了指定的key,則返回true.更一般的情況是,當且僅當map包含了一個key的映射
* 映射情況是:key==null ? k==null : key.equals(k),此時返回true.
*/
boolean containsKey(Object key);
/**
* 如果map中至少有一個key能映射到指定的value,那么就返回true.更一般的情況是,
* 當且僅當value==null ? v==null : value.equals(v)條件成立,才返回true.
* 在所有map接口的實現(xiàn)類中,這一操作都需要map大小的線性時間來完成.
*/
boolean containsValue(Object value);
/**
* 返回指定key映射的value.如果map沒有指定的key,則返回null.
*/
V get(Object key);
//三個返回key挪凑,value,key-value的集合
/**
* 此方法:返回map包含所有的key的一個set集合視圖
*/
Set<K> keySet();
/**
* values方法返回map內(nèi)存儲的所有值的集合(畢竟值集合中,值可以有重復(fù)的,所以此方法和上面的返回的
* key集合的結(jié)果類型不一樣,因為key肯定都是不同的).
*/
Collection<V> values();
/**
* 此方法返回map里存儲的所有映射的視圖.
*/
Set<Map.Entry<K, V>> entrySet();
//兩個覆蓋object的方法
/**
* 用于對比兩個map是否相等.
* 如果給定的對象是一個map且兩個map的映射一致,則返回true.
* 一般,兩個map的映射一致,要滿足的條件是:m1.entrySet().equals(m2.entrySet())
* 這就保證了實現(xiàn)了map接口的不同類對于equals方法的使用才是正確的.
*/
boolean equals(Object o);
/**
* 返回map的哈希值逛艰,map的哈希值被定義為:這個map的entrySet視圖的每一個條目的哈希值的總和.
* 這就保證了任意兩個map相等,則他們的哈希值一定相等,這也是Object類對哈希值的普遍要求(哈希值作為兩個對象相等的必要非充分條件).
*/
int hashCode();
/**
* map條目(key-value對),Map.entrySet方法返回的就是map的集合視圖,map視圖中的元素就是來源于此類.
* 獲取map條目的唯一方式就是來源于集合視圖的迭代器.只有在迭代的過程中,Map.Entry對象才是有效的;
* 通常,如果通過迭代器獲得的map條目,在遍歷過程中,作為后臺支持的map被修改了,那么map條目會如何被影響,對此
* 并沒有做出具體規(guī)定(當然此處說的map修改不包括setValue方法的調(diào)用).
*/
interface Entry<K,V> {
/**
* 獲取當前map條目對應(yīng)的key
*/
K getKey();
/**
* 返回map條目對應(yīng)的value值.
*/
V getValue();
/**
* 用指定值替換當前條目中的value
*/
V setValue(V value);
/**
* 將指定對象和當前條目做比較,如果給定的對象是一個條目并且兩個條目代表同一個映射,則返回true.
*/
boolean equals(Object o);
/**
* 返回map條目的哈希值
*/
int hashCode();
/**
* 返回一個比較map.entry的比較器,按照key的自然順序排序躏碳,返回的比較器支持序列化
* @since 1.8
*/
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.enty的比較器,按照value的自然順序排序,返回的比較器支持序列化
* @since 1.8
*/
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的比較器,根據(jù)傳入比較器對key排序散怖,如果傳入的比較器支持序列化,則返回的結(jié)果比較器也支持序列化.
* @since 1.8
*/
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());
}
/**
* 返回一個map.entry的比較器,根據(jù)傳入比較器對value排序菇绵,如果傳入的比較器支持序列化,則返回的結(jié)果比較器也支持序列化
* @since 1.8
*/
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());
}
}
//1.8新增
/**
* 返回指定key對應(yīng)的value,如果沒有對應(yīng)的映射,則返回傳入?yún)?shù)中的默認值defaultValue
* @since 1.8
*/
default V getOrDefault(Object key, V defaultValue) {
V v;
return (((v = get(key)) != null) || containsKey(key))
? v
: defaultValue;
}
/**
* 對map中每一個entry執(zhí)行action中定義對操作,直到全部entry執(zhí)行完成or執(zhí)行中出現(xiàn)異常為止
* @since 1.8
*/
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中每一個entry,將其value替換成BiFunction接口返回的值.直到所有entry替換完or出現(xiàn)異常為止
* @since 1.8
*/
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);
}
}
}
/**
* 如果指定的鍵尚未與值相關(guān)聯(lián)(或被映射為null),則將它與給定的值相關(guān)聯(lián)并返回null,否則返回當前值镇眷。
* @since 1.8
*/
default V putIfAbsent(K key, V value) {
V v = get(key);
if (v == null) {
v = put(key, value);
}
return v;
}
/**
* 如果給定的參數(shù)key和value在map中是一個entry,則刪除這個entry.
* @since 1.8
*/
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在map中有entry,則為指定key的entry,用新value替換舊的value
* @since 1.8
*/
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在map中有value,則用參數(shù)value進行替換
* @since 1.8
*/
default V replace(K key, V value) {
V curValue;
if (((curValue = get(key)) != null) || containsKey(key)) {
curValue = put(key, value);
}
return curValue;
}
/**
* 如果指定key在map中沒有對應(yīng)的value,則使用輸入?yún)?shù),即函數(shù)接口mappingfunction為其計算一個value.
* 如果計算value不為null,則將value插入map中咬最,如果計算function返回結(jié)果為null,則不插入任何映射。
* @since 1.8
*/
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;
}
/**
* 如果map中存在指定key對應(yīng)的value,且不為null,則本方法會嘗試使用function,并利用key生成一個新的value
* 如果function接口返回null,map中原entry則被移除.如果function本身拋出異常,則當前map不會發(fā)生改變.
* @since 1.8
*/
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和value計算一個新映射欠动,比如:向一個value映射中新增或者拼接一個String丹诀。
* 如果function接口返回null,則map中原entry被移除(如果本來就不存在,則不執(zhí)行移除操作).
* 如果function本身拋出(非檢查型)異常,異常會被重新拋出,當前map也不會發(fā)生改變.
* @since 1.8
*/
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沒有value,或者其value為null,則將其改為給定的非null的value
* 否則,用給定的function返回值替換原value.
* 如果給定參數(shù)value和function返回結(jié)果都為null,則刪除map中這個entry.
* 這一方法常用于:對一個key合并多個映射的value時.
* 比如:要創(chuàng)建或追加一個String給一個值映射.
* 如果function返回null,則map中原entry被移除.如果function本身拋出異常,則異常會被重新拋出,且當前map不會發(fā)生更改.
* @since 1.8
*/
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;
}
}
}
上述注釋按照JDK進行翻譯,如有不正確支出翁垂,望提出。