HashMap分析-基础属性与结构

303 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第14天,点击查看活动详情

HashMap的简述

在 JDK 1.7 中, HashMap 是以数组加链表的方式组成的,JDK 1.8 之后新增了红黑树的结构,当链表大于 8 并且容量大于 64 时,链表结构会转换成红黑树结构。

哈希桶

其中数组中的元素,称之为哈希桶,源代码:

static class Node<K,V> implements Map.Entry<K,V> {
    final int hash;
    final K key;
    V value;
    Node<K,V> next;

    Node(int hash, K key, V value, Node<K,V> next) {
        this.hash = hash;
        this.key = key;
        this.value = value;
        this.next = next;
    }

    public final K getKey()        { return key; }
    public final V getValue()      { return value; }
    public final String toString() { return key + "=" + value; }

    public final int hashCode() {
        return Objects.hashCode(key) ^ Objects.hashCode(value);
    }

    public final V setValue(V newValue) {
        V oldValue = value;
        value = newValue;
        return oldValue;
    }

    public final boolean equals(Object o) {
        if (o == this)
            return true;
        if (o instanceof Map.Entry) {
            Map.Entry<?,?> e = (Map.Entry<?,?>)o;
            if (Objects.equals(key, e.getKey()) &&
                Objects.equals(value, e.getValue()))
                return true;
        }
        return false;
    }
}

其主要结构包含了四个主要的字段:hash、key、value、next

HashMap基础属性

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 表示HashMap 初始化长度,默认为16。

static final int MAXIMUM_CAPACITY = 1 << 30; // 1073741824 HashMap 的最大长度

static final float DEFAULT_LOAD_FACTOR = 0.75f; 默认的加载因子,也叫扩容因子,用来判断HashMap什么时候会进行扩容。加入扩容因子是0.5,HashMap的初始化容量是32,则HashMap找那个有32*0.5=16个元素时,就会进行扩容。

默认设置为0.75,也是出于性能考虑,当扩容因子设置得比较大时,扩容的条件会提高,扩容的频率会变低,此时发生Hash冲突的概率也会提升。如果设置得比较小,则扩容的条件更低,占用的空间更多,元素存储的位置也比较稀疏,但相应的发生哈希冲突的可能性就会变小。

static final int TREEIFY_THRESHOLD = 8; 当链表长度大于此值(默认为8)且容量大于 64 时

static final int UNTREEIFY_THRESHOLD = 6; 转换链表的临界值,当元素小于此值时,会将红黑树结构转换成链表结构