专栏名称: java那些事
分享java开发中常用的技术,分享软件开发中各种新技术的应用方法。每天推送java技术相关或者互联网相关文章。关注“java那些事”,让自己做一个潮流的java技术人!《java程序员由笨鸟到菜鸟》系列文章火热更新中。
目录
相关文章推荐
芋道源码  ·  谈一谈 分库分表 vs NewSQL数据库 ·  11 小时前  
Java编程精选  ·  成年人欲望程度排行榜TOP 10 ·  2 天前  
芋道源码  ·  如何搭建漂亮的 SpringBoot 脚手架? ·  2 天前  
51好读  ›  专栏  ›  java那些事

Java学习 提高篇---HashMap 。

java那些事  · 公众号  · Java  · 2017-02-23 16:33

正文

请到「今天看啥」查看全文


数据结构

三、数据结构

我们知道在Java中最常用的两种结构是数组和模拟指针(引用),几乎所有的数据结构都可以利用这两种来组合实现,HashMap也是如此。实际上HashMap是一个“链表散列”,如下是它数据结构:

从上图我们可以看出HashMap底层实现还是数组,只是数组的每一项都是一条链。其中参数initialCapacity就代表了该数组的长度。下面为HashMap构造函数的源码:

public HashMap(int initialCapacity, float loadFactor) {        //初始容量不能        if (initialCapacity                     + initialCapacity);        //初始容量不能 > 最大容量值,HashMap的最大容量值为2^30
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;        //负载因子不能         if (loadFactor                     + loadFactor);        // 计算出大于 initialCapacity 的最小的 2 的 n 次方值。
        int capacity = 1;        while (capacity             capacity         this.loadFactor = loadFactor;        //设置HashMap的容量极限,当HashMap的容量达到该极限时就会进行扩容操作
        threshold = (int) (capacity * loadFactor);        //初始化table数组
        table = new Entry[capacity];
        init();
    }

从源码中可以看出,每次新建一个HashMap时,都会初始化一个table数组。table数组的元素为Entry节点。

static class Entry implements Map.Entry {        final K key;
        V value;
        Entry next;        final int hash;        /**
         * Creates new entry.         */
        Entry(int h, K k, V v, Entry n) {
            value = v;
            next = n;
            key = k;
            hash = h;
        }
        .......
    }

其中Entry为HashMap的内部类,它包含了键key、值value、下一个节点next,以及hash值,这是非常重要的,正是由于Entry才构成了table数组的项为链表。

上面简单分析了HashMap的数据结构,下面将探讨HashMap是如何实现快速存取的。

四、存储实现:put(key,vlaue)

首先我们先看源码 public V put(K key, V value) {        //当key为null,调用putForNullKey方法,保存null与table第一个位置中,这是HashMap允许为null的原因

        if (key == null)            return putForNullKey(value);        //计算key的hash值
        int hash = hash(key.hashCode());                  ------(1)        //计算key hash 值在 table 数组中的位置
        int i = indexFor(hash, table.length);             ------(2)        //从i出开始迭代 e,找到 key 保存的位置
        for (Entry e = table[i]; e != null; e = e.next) {
            Object k;            //判断该条链上是否有hash值相同的(key相同)            //若存在相同,则直接覆盖value,返回旧value
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;    //旧值 = 新值
                e.value = value;
                e.recordAccess(this);                return oldValue;     //返回旧值            }
        }        //修改次数增加1
        modCount++;        //将key、value添加至i位置处        addEntry(hash, key, value, i);        return null;
    }






请到「今天看啥」查看全文