一、前言
如大家所知,在Java集合分成三大类,Set、List、Map,其中Set和Map均为Collection接口的子接口。Map是以键值对的结果来存储数据的,将键映射到值的对象。映射不能包含重复的键;每个键最多只能映射到一个值。
二、Map
Map这个接口代替了Dictionary类,Dictionary类是一个完全抽象的类,而不是接口。
Map的子接口和实现类如下(Map接口):
Interface Map<K,V>
Type Parameters:
K - the type of keys maintained by this map
V - the type of mapped values
All Known Subinterfaces:
Bindings, ConcurrentMap<K,V>, ConcurrentNavigableMap<K,V>, LogicalMessageContext, MessageContext, NavigableMap<K,V>, SOAPMessageContext, SortedMap<K,V>
All Known Implementing Classes:
AbstractMap, Attributes, AuthProvider, ConcurrentHashMap, ConcurrentSkipListMap, EnumMap, HashMap, Hashtable, IdentityHashMap, LinkedHashMap, PrinterStateReasons, Properties, Provider, RenderingHints, SimpleBindings, TabularDataSupport, TreeMap, UIDefaults, WeakHashMap
Map是一个接口,一个map不能包含重复的key,每个key只能映射唯一一个value.
接下来我们将针对ConcurrentHashMap、HashMap、Hashtable、LinkedHashMap、TreeMap进行分析
先来看看Map接口的源码
/*
* @author Josh Bloch
* @see HashMap
* @see TreeMap
* @see Hashtable
* @see SortedMap
* @see Collection
* @see Set
* @since 1.2
*/
public interface Map<K,V> {
// Query Operations 查询操作
int size();
boolean isEmpty();
boolean containsKey(Object key);
boolean containsValue(Object value);
V get(Object key);
// Modification Operations 修改操作
V put(K key, V value);
V remove(Object key);
// Bulk Operations 批量操作
//将所有映射从指定映射复制到此映射
void putAll(Map<? extends K, ? extends V> m);
//删除所有映射
void clear();
// Views 视图
//所有key的集合,不允许重复
Set<K> keySet();
//所有value的集合
Collection<V> values();
//所有键值对的集合,不允许重复
Set<Map.Entry<K, V>> entrySet();
interface Entry<K,V> {
K getKey();
V getValue();
V setValue(V value);
boolean equals(Object o);
int hashCode();
/**
* @since 1.8 返回一个比较器,比较的规则是key的自然大小
*/
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());
}
/**
* @since 1.8 返回一个比较器,比较规则是value的自然大小
*/
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());
}
/**
* @since 1.8 返回一个比较器,比较规则用cmp参数传入,比较的是key
*/
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());
}
/**
* @since 1.8 返回一个比较器,比较规则用cmp参数传入,比较的是value
*/
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());
}
}
// Comparison and hashing 比较和散列
int hashCode();
// Defaultable methods @since 1.8
default V getOrDefault(Object key, V defaultValue) {
V v;
return (((v = get(key)) != null) || containsKey(key)) ? v : defaultValue;
}
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. 这通常意味着entry不再在映射中
throw new ConcurrentModificationException(ise);
}
action.accept(k, v);
}
}
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);
}
// ise thrown from function is not a cme.从函数抛出的ise不是cme
v = function.apply(k, v);
try {
entry.setValue(v);
} catch(IllegalStateException ise) {
throw new ConcurrentModificationException(ise);
}
}
}
default V putIfAbsent(K key, V value) {
V v = get(key);
if (v == null) {
v = put(key, value);
}
return v;
}
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;
}
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;
}
default V replace(K key, V value) {
V curValue;
if (((curValue = get(key)) != nul