容器源码分析之——Map

一、Map 整体结构

1.1 类继承结构

1.2 实现类简介

Map是一种把键对象和值对象映射的集合,是一个顶层接口,定义了Map的基本操作。它的每一个元素都包含一对键对象和值对象。 Map没有继承Collection接口。

  • AbstractMap:实现了Map接口的抽象类。Map的基本实现,其他Map的实现类可以通过继承AbstractMap来减少编码量。
  • SortedMap:继承Map。保证按照键的升序排列的映射,对entrySet、keySet和values方法返回的结果进行迭代时,顺序就会反映出来。
  • NavigableMap:继承SortedMap,含有返回特定条件最近匹配的导航方法。
  • HashMap:Map接口基于哈希表的实现,是使用频率最高的用于键值对处理的数据类型。它根据键的hashCode值存储数据,大多数情况下可以直接定位到它的值,特点是访问速度快,遍历顺序不确定,线程不安全,最多允许一个key为null,允许多个value为null。可以用 Collections的synchronizedMap方法使HashMap具有线程安全的能力,或者使用ConcurrentHashMap类。
  • HashTable:Hashtable和HashMap从存储结构和实现来讲有很多相似之处,不同的是它继承自Dictionary类,而且是线程安全的,另外Hashtable不允许key和value为null。并发性不如ConcurrentHashMap,因为ConcurrentHashMap引入了分段锁。Hashtable不建议在新代码中使用,不需要线程安全的场合可以使用HashMap,需要线程安全的场合可以使用ConcurrentHashMap。
  • LinkedHashMap: LinkedHashMap继承了HashMap,是Map接口的哈希表和链表实现。它维护着一个双重链表。此链表定义了迭代顺序,该迭代顺序可以是插入顺序或者是访问顺序。
  • WeakedHashMap: 以弱键实现的基于哈希表的Map。在WeakHashMap中,当某个键不再正常使用时,将自动移除其条目。
  • TreeMap : Map接口基于红黑树的实现。

二、源码分析

2.1 注释

Map是一种以键值对形式存储的对象。Map中不能包含重复的keys,每个key最多只能对应一个value。
此接口代替了Dictionary类,此类是一个完全的抽象类。
Map接口提供了三种集合视图,分别是键集,值集,键值集。Map的顺序定义在map集合视图的迭代器中。一些实现如TreeMap,保证了特定的顺序;其他实现如HashMap,则不保证。
注意:当使用可变对象作为map的keys的时候,要注意重写equals和hashCode方法。
所有的通用map实现类都应该提供2种标准的构造函数:一个void(无参数)的构造函数,此构造函数创建一个空map;和一个参数类型为Map的单参数的构造函数,允许以与参数相同的键值对创建一个新的map。实际上,后一种构造方法允许用户复制任何一种map。
一些map可能会对它的kyes和values更加严格,比如对于Null值。

2.2 定义

public interface Map<K,V>

此接口为顶层接口。

2.3 域

Map接口并没有自己的域变量。

查询操作(Query Operations)

    /**
	 * 返回map中键值对的数量
	 * 如果map中包含的元素大于Integer.MAX_VALUE,那么返回Integer.MAX_VALUE
     *
     * @return the number of key-value mappings in this map
     */
    int size();

    /**
	 * map中有键值对则返回true,没有则返回false
     */
    boolean isEmpty();

    /**
	 * 有指定的key则返回true
     */
    boolean containsKey(Object key);

    /**
	 * 有一个或以上的keys对应指定的value则返回true
     */
    boolean containsValue(Object value);

    /**
	 * 有该key则返回对应的value,没有则返回null
     */
    V get(Object key);

2.5 修改操作(Modification Operations)

   /**
     * 在map中添加新的键值对,如果指定key已经存在,则新的value将取代旧value
     */
    V put(K key, V value);

    /**
     * 删除map中的以指定的key组成的键值对,并返回对应的value
	 * 如果没有该key,则返回null
     */
    V remove(Object key);

2.6 块操作(Bulk Operations)

    /**
	 * 将指定的map全部拷贝到调用该函数的map中
	 * 如果在这个过程中,指定的map发生修改,那么最后拷贝的结果将是不确定的;
	 * 即不确定拷贝的是修改前还是修改后的。
     */
    void putAll(Map<? extends K, ? extends V> m);

    /**
	 * 删除此map中所有的键值对,结束后map为空
     */
    void clear();

2.7 视图

    /**
	 * 返回该map中所有keys的一个视图(属性为Set)。此Set被该map支持,因此改变map也会改变此Set,反之亦然。
	 * 如果在迭代器使用此set时,map被修改,那么迭代器的结果是不能预料的(迭代器通过自己的remove方法是安全的)。
	 * 此set支持元素删除,通过<tt>Iterator.remove</tt>, <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>完成
	 * 此set不支持<tt>add</tt> or <tt>addAll</tt>操作
     */
    Set<K> keySet();

    /**
	 * 返回该map所有values的一个视图(属性为Collection,表明可重复)此Collection被该map支持,因此改变map也会改变此Set,反之亦然。
	 * 如果在迭代器使用此Collection时,map被修改,那么迭代器的结果是不能预料的(迭代器通过自己的remove方法是安全的)。
	 * 支持元素删除,通过<tt>Iterator.remove</tt>, <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>完成
	 * 不支持<tt>add</tt> or <tt>addAll</tt>操作
     */
    Collection<V> values();

    /**
      * 返回该map中所有键值对的一个视图(属性为Set)。此Set被该map支持,因此改变map也会改变此Set,反之亦然。
	 * 如果在迭代器使用此set时,map被修改,那么迭代器的结果是不能预料的(迭代器通过自己的remove方法是安全的)。
	 * 此set支持元素删除,通过<tt>Iterator.remove</tt>, <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>完成
	 * 此set不支持<tt>add</tt> or <tt>addAll</tt>操作
     */
    Set<Map.Entry<K, V>> entrySet();

2.8 Comparison and hashing

// Comparison and hashing

    boolean equals(Object o);

    int hashCode();

2.9 默认方法(实际中大部分方法很少用到)

   // Defaultable methods

    /**
	 * map中有指定的key时返回对应的value,否则返回默认值defaultValue
     * @since 1.8
     */
    default V getOrDefault(Object key, V defaultValue) {
        V v;
        return (((v = get(key)) != null) || containsKey(key))
            ? v
            : defaultValue;
    }
        /**
	 * 对此映射中的每个条目执行给定的操作,直到所有条目都被处理或操作引发异常。
	 * action和BiConsumer是什么?
	 * forEach的使用场景是什么?
     * @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);
        }
    }

    /**
	 * 将每个条目的值替换为对该条目调用给定函数的结果,直到所有条目都被处理或该函数抛出异常。
	 * BiFunction是啥,使用场景是啥?
     * @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);
            }
        }
    }

    /**
	 * 仅当指定的密钥当前映射到指定的值时删除该条目
     * @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;
    }

    /**
	 * 仅当当前映射到指定的值时,才能替换指定键的条目
     * @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;
    }

    /**
     * 只有当目标映射到某个值时,才能替换指定键的条目。
     * @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;
    }

    /**
	 * 如果指定的键尚未与值相关联(或映射到 null ),则尝试使用给定的映射函数计算其值,
	 * 并将其输入到此映射中,除非 null 。
     * @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;
        }
    }

    /**
	 * 尝试计算指定键的映射及其当前映射的值(如果没有当前映射, null )。
     * @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;
        }
    }

    /**
     * 如果指定的键尚未与值相关联或与null相关联,则将其与给定的非空值相关联。
     * @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;
    }

2.10 内部接口

Interface Entry<K, V>{}

   /**
     * map的entry(entry可翻译为条目),Map.entrySet()方法返回的就是一个map的集合视图,其元素就是这个entry
	 * 集合视图的迭代器是获得一个map的entry引用的唯一方式。
	 * 只有在迭代器中,这些Map.Entry对象是可用的
     *
     * @see Map#entrySet()
     * @since 1.2
     */
    interface Entry<K,V> {
        /**
         * Returns the key corresponding to this entry.
         *
         */
        K getKey();

        /**
		 * 返回此entry的value。如果键值对已经被remove了,那么此调用的结果undefined(未定义)
         */
        V getValue();

        /**
         * Replaces the value corresponding to this entry with the specified
         * value (optional operation).  (Writes through to the map.)  The
         * behavior of this call is undefined if the mapping has already been
         * removed from the map (by the iterator's <tt>remove</tt> operation).
         */
        V setValue(V value);

        /**
		 * 判断两个键值对是否相等
         */
        boolean equals(Object o);

        /**
         * Returns the hash code value for this map entry.  The hash code
         * of a map entry <tt>e</tt> is defined to be: <pre>
         *     (e.getKey()==null   ? 0 : e.getKey().hashCode()) ^
         *     (e.getValue()==null ? 0 : e.getValue().hashCode())
         */
        int hashCode();

        /**
		 * 按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());
        }

        /**
		 * 按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());
        }

        /**
		 * 根据key用指定的比较器排序
         * @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());
        }

        /**
         * 根据value用指定的比较器排序
         * @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());
        }
    }

三、AbstractMap

3.1 注释

/**

  • 1、此类提供了Map接口的基本实现,使得实现Map接口变得更简单
  • 2、为了实现一个不可修改的map,开发者只需要去继承这个类,并提供entrySet的实现
  • Typically, the returned set will, in turn, be implemented atop AbstractSet.
  • This set should not support the add or remove methods, and its iterator
  • should not support the remove method.
  • 3、为了实现一个可修改的map, 开发者必须另外覆盖此类的put方法
  • 并且,entrySet().iterator()返回的iterator必须额外实现它的remove方法
  • 4、此类的中非抽象方法必要时可以被覆盖
  • @since 1.2
    */

3.2 核心方法

AbstrctMap的源码就是提供了Map接口的一些简单实现。主要是利用Map中三种视图:

Set<Entry<K,V>> entrySet()
Set<K>        keySet;
Collection<V> values;

再结合“Set”或者“Collection”本身的迭代器或一些域变量(size)进行实现。如果有疑问,可以简单对照看一看即可。

四、SortedMap

SortedMap也是一个接口,继承自Map接口,Sorted表示它是一个有序的键值映射。
SortedMap的排序方式有两种:自然排序和指定比较器排序。插入有序的SortedMap的所有元素都必须实现Comparable接口(或被指定的比较器所接受)。

4.1 核心方法

Comparator<? super K> comparator(); 
 SortedMap<K,V> subMap(K fromKey, K toKey);
 SortedMap<K,V> headMap(K toKey);
 SortedMap<K,V> tailMap(K fromKey);
 K firstKey();
 K lastKey();
 Set<K> keySet();
 Collection<V> values();
 Set<Map.Entry<K, V>> entrySet();
原文地址:https://www.cnblogs.com/cleverziv/p/14350982.html