博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HashMap详解
阅读量:5891 次
发布时间:2019-06-19

本文共 5698 字,大约阅读时间需要 18 分钟。

hot3.png

做了两年的java,感觉技术上没多大提升,特别是呆了一年外企,整理感觉自己都萎靡,不爱学习!

所以,写个帖子记下在网上看到的东西以及自己要去学习的内容!
努力奋斗!
1.HashMap的实现--------------------<在看>
   1.1 HashMap 的默认size是16,默认临界值是 12,默认的基数0.75。
   1.2 HashMap 的最大size是1<<30
   1.3 HashMap 中 transfer方法理解:

           void transfer(Entry[] newTable) {        Entry[] src = table;        int newCapacity = newTable.length;        for (int j = 0; j < src.length; j++) {            Entry
 e = src[j];//标记1            if (e != null) {                src[j] = null;//标记2                do {                    Entry
 next = e.next;//标记3                    int i = indexFor(e.hash, newCapacity);//标记4                    e.next = newTable[i];//标记5                    newTable[i] = e;//标记6                    e = next;//标记7                } while (e != null);            }        }    }

标记1:从Entry 数组中获取到 oldTable中需要往newTable 插入的entry实例e。

    标记2:回收oldTable的内存。
    标记3:使用临时变量存储e.next的值,以便下次获取链表的下个需要遍历的值,直到e.next的值为空。
    标记4:根据e的hash值和新表中的容量计算e需要放置在新数组中的index值。
    标记5:把新数组index位置的值传递给e.next.
    标记6:把e放置在新数组index的位置下。
    标记7:重新设置e的值,把老数组e的next值传递给e.继续下一轮循环,直到e的next为空。
   1.4 HashMap 中 put 方法:

 public V put(K key, V value) {        if (key == null)            return putForNullKey(value);        //根据hash算法获取需要插入数据的hash值        int hash = hash(key.hashCode());        //根据hash值,计算将要插入数组的index值        int i = indexFor(hash, table.length);        //如果该index下,存在链表值,遍历该链表,对比        //链表中的每一个entry的实例的hash值和key        //是否和需要插入的key和key的hash值相同。        //如果相同:跟新原entry下的value;保持key,index和hash值不        //变。        //如果不相同:把新纪录插入到数组中。        for (Entry
 e = table[i]; e != null; e = e.next) {            Object k;            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {                V oldValue = e.value;                e.value = value;                e.recordAccess(this);                return oldValue;            }        }        modCount++;        addEntry(hash, key, value, i);        return null;    }

1.5 HashMap中的addEntry方法:

   void addEntry(int hash, K key, V value, int bucketIndex) {    Entry
 e = table[bucketIndex];        table[bucketIndex] = new Entry
(hash, key, value, e);        //如果数组table的长度大于临界值,将table进行扩容,长度为原来的        //两倍。        if (size++ >= threshold)            resize(2 * table.length);    }

1.6 HashMap中的静态内部类Entry:

 static class Entry
 implements Map.Entry
 {        final K key;        V value;        Entry
 next;        final int hash;        /**         * h:新创建的entry实例的hash值。         * k:键值         * v:值         * n:链表中但前entry实例的下一个entry的值。         */        Entry(int h, K k, V v, Entry
 n) {            value = v;            next = n;            key = k;            hash = h;        }        public final K getKey() {            return key;        }        public final V getValue() {            return value;        }        public final V setValue(V newValue) {        V oldValue = value;            value = newValue;            return oldValue;        }        public final boolean equals(Object o) {            if (!(o instanceof Map.Entry))                return false;            Map.Entry e = (Map.Entry)o;            Object k1 = getKey();            Object k2 = e.getKey();            if (k1 == k2 || (k1 != null && k1.equals(k2))) {                Object v1 = getValue();                Object v2 = e.getValue();                if (v1 == v2 || (v1 != null && v1.equals(v2)))                    return true;            }            return false;        }        public final int hashCode() {            return (key==null   ? 0 : key.hashCode()) ^                   (value==null ? 0 : value.hashCode());        }        public final String toString() {            return getKey() + "=" + getValue();        }          void recordAccess(HashMap
 m) {        }        void recordRemoval(HashMap
 m) {        }    }

  1.7 HashMap中的remove()方法:

final Entry
 removeEntryForKey(Object key) {        //获取hash值,如果key是null,hash值为0.        int hash = (key == null) ? 0 : hash(key.hashCode());        //获取该key的下标值。        int i = indexFor(hash, table.length);        Entry
 prev = table[i];        Entry
 e = prev;        while (e != null) {            Entry
 next = e.next;            Object k;            if (e.hash == hash &&                ((k = e.key) == key || (key != null && key.equals(k)))) {                modCount++;                size--;                if (prev == e)                  //移动数组,用需要删除数组后一位置的值覆盖当前位置                    table[i] = next;                else                       //把需要删除的值,用当前链表中的下一个值                //进行覆盖,依次用下一个覆盖上一个,直到                //需要删除纪录后的每一数据都向前移动一位。                    prev.next = next;                e.recordRemoval(this);                return e;            }            prev = e;            e = next;        }        return e;    }

有代码可得知:hashmap的删除不知是单单的把需要删除的纪录内存释放(设置为null)。而是

移动需要删除纪录后的每一个元素来覆盖前元素,释放最后一个值。
    1.8 HashMap 中的get()方法:

   public V get(Object key) {        if (key == null)            return getForNullKey();        int hash = hash(key.hashCode());        for (Entry
 e = table[indexFor(hash, table.length)];             e != null;             e = e.next) {            Object k;            if (e.hash == hash && ((k = e.key) == key || key.equals(k)))                return e.value;        }        return null;    }

从上面代码可以得知,当key为空的时候,hashmap从table[0]的位置获取专门存取null键的位置获取值,key不为空的时候,根据传入 key的hash值,获取index值(数组下标),然后 遍历该index下的entry链表,比对该hash值下所有的key,如果有key和传入的key相同,

获取该key下的value.
    1.9 HashMap的结构图(见附件)

19160742_NOpS.gif

转载于:https://my.oschina.net/Sheamus/blog/617719

你可能感兴趣的文章
Java对象模型
查看>>
记那次失败了的面试
查看>>
程序包+创建包规范+创建包体+删除程序包
查看>>
css写出三角形(兼容IE)
查看>>
Vue过渡效果之JS过渡
查看>>
3-继承
查看>>
java中如何实现类似goto的作法
查看>>
Switch入门第二讲
查看>>
iOS学习过程中遇到的一些有用的小功能(8/13更新)
查看>>
海归千千万 为何再无钱学森
查看>>
更新日志(建议升级到2017.1.18a) && 更新程序的方法
查看>>
taro 填坑之路(一)taro 项目回顾
查看>>
vue2.0 仿手机新闻站(六)详情页制作
查看>>
HTML超文本标记语言-基础标签整理
查看>>
20155222 c语言实现pwd命令
查看>>
FreeRTOS的内存管理
查看>>
TensorFlow 1.9官网树莓派安装教程
查看>>
Linux主机如何用ssh去登录docker容器的步骤
查看>>
android手势事件 快速移动 长按触摸屏 按下触摸屏,并拖动
查看>>
前端之js-本地存储-localStorage && IndexedDB
查看>>