三、Map

先来讲一下Map,Map和Collection完全不是一个系列的,按理说讲完Collection的List,应该接着讲Collection的Set,但是因为Set中很多实现是基于Map来实现的,所以将Map提前。Map是一个接口,存储内容是键值对key-value,键不可重复。

1.HashMap

AbstractMap是实现Map接口的抽象类,HashMap继承于AbstractMap。

Map的API:(JDK1.8版本新增较多,为25个详见 https://docs.oracle.com/javase/8/docs/api/index.html)

abstract void                 clear()
abstract boolean              containsKey(Object key)
abstract boolean              containsValue(Object value)
abstract Set<Entry<K, V>>     entrySet()
abstract boolean              equals(Object object)
abstract V                    get(Object key)
abstract int                  hashCode()
abstract boolean              isEmpty()
abstract Set<K>               keySet()
abstract V                    put(K key, V value)
abstract void                 putAll(Map<? extends K, ? extends V> map)
abstract V                    remove(Object key)
abstract int                  size()
abstract Collection<V>        values()

 AbstractMap的API只比Map新增了两个方法:

String               toString()
Object               clone()

Map.Entry是Map类的静态接口,其API为 :

abstract boolean     equals(Object object)
abstract K           getKey()
abstract V           getValue()
abstract int         hashCode()
abstract V           setValue(V object)

 HashMap是线程不安全的,其key和value都可以是null。此外,HashMap不是有序的映射(什么是有序? 2019.1.1补:遍历的顺序和插入的顺序无直接关系)。

(1)HashMap成员域

HashMap基本成员域有:

    transient Node<K,V>[] table;
    transient Set<Map.Entry<K,V>> entrySet;
    transient int size;
    transient int modCount;
    int threshold;
    final float loadFactor;

table即为实现hashmap的核心,数组的每个元素是Node类型,本质上是一个链表,用于存储键值对。JDK7以下的table可以用下图来表示原理:

集合(三) HashMap

size是存储键值对的个数,loadfactor称为装载因子,默认为0.75,threshold=capacity*loadfactor,如果size大于阈值threshold就要进行扩容,而容量一般是2的幂数。因此loadfactor作用是为了使哈希中的存储更加均匀,减小冲突。显而易见的是,如果想节省存储空间,那么loadfactor应该设置的大一点(记住减少扩容就很好理解了),若想提高查询效率,loadfactor应该设置的大一点。

Note:桶的数量即为capacity。

(2)HashMap的构造函数

HashMap共有四种构造函数:

public HashMap()
public HashMap(int initialCapacity)
public HashMap(int initialCapacity,float loadFactor)
public HashMap(Map<? extends K,? extends V> m)

 HashMap默认设置容量capacity为16,而装载因子loadfactor为0.75,也可以按照上面构造函数自定义。

详细的构造函数如下面的代码:

    /**
     * Constructs an empty <tt>HashMap</tt> with the specified initial
     * capacity and load factor.
     *
     * @param  initialCapacity the initial capacity
     * @param  loadFactor      the load factor
     * @throws IllegalArgumentException if the initial capacity is negative
     *         or the load factor is nonpositive
     */
    public HashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +
                                               loadFactor);
        this.loadFactor = loadFactor;
        this.threshold = tableSizeFor(initialCapacity);
    }

    /**
     * Constructs an empty <tt>HashMap</tt> with the specified initial
     * capacity and the default load factor (0.75).
     *
     * @param  initialCapacity the initial capacity.
     * @throws IllegalArgumentException if the initial capacity is negative.
     */
    public HashMap(int initialCapacity) {
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    }

    /**
     * Constructs an empty <tt>HashMap</tt> with the default initial capacity
     * (16) and the default load factor (0.75).
     */
    public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
    }

    /**
     * Constructs a new <tt>HashMap</tt> with the same mappings as the
     * specified <tt>Map</tt>.  The <tt>HashMap</tt> is created with
     * default load factor (0.75) and an initial capacity sufficient to
     * hold the mappings in the specified <tt>Map</tt>.
     *
     * @param   m the map whose mappings are to be placed in this map
     * @throws  NullPointerException if the specified map is null
     */
    public HashMap(Map<? extends K, ? extends V> m) {
        this.loadFactor = DEFAULT_LOAD_FACTOR;
        putMapEntries(m, false);
    }
HashMap Construct Functions

相关文章: