Java8—HashMap解析

摘要

HashMap的内部表示在Java8中得到很大的改进,比如说在Java7中实现HashMap需要1k行代码,而在Java8中需要2K行代码。在Java8中内部仍然以数组实现,但是以节点(Node)来作为Entry存储信息,并且同样也包括链表。

一、重要的概念

从结构实现来讲,HashMap是数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的,如下如所示。

这里写图片描述

Node是HashMap的一个内部类,实现了Map.Entry接口,本质是就是一个映射(键值对)。上图中的每个黑色圆点就是一个Node对象。

Node源代码如下:

    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;
        }
    }

Node是最核心的内部类,它包装了key-value键值对,允许调用setValue方法直接改变Node的value域。(1.8的ConcurrentHashMap中对Node的value和next属性设置了volatile同步锁(与JDK7的Segment相同),它不允许调用setValue方法直接改变Node的value域,它增加了find方法辅助map.get()方法。)

它实现了Map.Entry接口。其内部的变量含义也很明确,hash值、key\value对和实现链表和红黑树所需要的指针索引。

  既然知道了HashMap的基本结构,那么这些变量的默认值都是多少呢?我们再看一下HashMap定义的一些常量:

    //默认的初始容量为16,必须是2的幂次
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; 

    //最大容量即2的30次方
    static final int MAXIMUM_CAPACITY = 1 << 30;

    //默认加载因子
    static final float DEFAULT_LOAD_FACTOR = 0.75f;

    //当put一个元素时,其链表长度达到8时将链表转换为红黑树
    static final int TREEIFY_THRESHOLD = 8;

    //链表长度小于6时,解散红黑树
    static final int UNTREEIFY_THRESHOLD = 6;

    //默认的最小的扩容量64,为避免重新扩容冲突,至少为4 * TREEIFY_THRESHOLD=32,即默认初始容量的2倍
    
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值