当前位置: 首页 > news >正文

重庆丰标建设网站石家庄做网络科技公司

重庆丰标建设网站,石家庄做网络科技公司,重视网站阵地建设,济宁贵网站建设一.麻烦讲述一下Hashmap的扩容原理 jdk1.8中的hashmap扩容原理 1.put流程图 首先贴一张图(图片来源于传送门#xff09;#xff0c;多谢大佬的美图#xff0c;此图已经完美的描述了put的整个流程#xff0c;我也就不想自己画了#xff0c;嘿嘿: 2.hashmap中几个比较重…一.麻烦讲述一下Hashmap的扩容原理 jdk1.8中的hashmap扩容原理 1.put流程图 首先贴一张图(图片来源于传送门多谢大佬的美图此图已经完美的描述了put的整个流程我也就不想自己画了嘿嘿: 2.hashmap中几个比较重要的成员变量 HashMap在底层数据结构上采用了数组链表红黑树在其源码中有几个比较重要的成员变量需要记住,这几个成员变量也是在扩容中肯定会遇到的: // 默认的初始化容量16,必须为2的幂 static final int DEFAULT_INITIAL_CAPACITY 1 4; // aka 16 //默认的负载因子0.75f static final float DEFAULT_LOAD_FACTOR 0.75f; //当某个桶的阈值大于8会将链表的结构转换为红黑树 static final int TREEIFY_THRESHOLD 8; //当某个桶的阈值小于6时会将原本的树结构转换为链表结构 static final int UNTREEIFY_THRESHOLD 6; //当Node数组的长度大于64才允许将链表转换为红黑树否则应该直接扩容而不是将链表进行树化 //此处的含义就是如果一个链表的长度超过了8但是Node数组的长度小于64的话一般以扩容来处理 而不是将链表树化 static final int MIN_TREEIFY_CAPACITY 64; //阈值capacity * load factor int threshold;3.扩容的详细步骤 public V put(K key, V value) {return putVal(hash(key), key, value, false, true); }final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {NodeK,V[] tab; NodeK,V p; int n, i;if ((tab table) null || (n tab.length) 0)n (tab resize()).length;if ((p tab[i (n - 1) hash]) null)tab[i] newNode(hash, key, value, null);else {NodeK,V e; K k;if (p.hash hash ((k p.key) key || (key ! null key.equals(k))))e p;else if (p instanceof TreeNode)e ((TreeNodeK,V)p).putTreeVal(this, tab, hash, key, value);else {for (int binCount 0; ; binCount) {if ((e p.next) null) {p.next newNode(hash, key, value, null);if (binCount TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);break;}if (e.hash hash ((k e.key) key || (key ! null key.equals(k))))break;p e;}}if (e ! null) { // existing mapping for keyV oldValue e.value;if (!onlyIfAbsent || oldValue null)e.value value;afterNodeAccess(e);return oldValue;}}modCount;if (size threshold)resize();afterNodeInsertion(evict);return null;}首先从put和putVal中我们发现扩容的核心源码是resize(): 在分析resize()方法之前我们首先了解一下在那些情况下hashmap会产生扩容动作 在hashmap中有三种情况会触发扩容,分别是: 第一种使用默认构造方法初始化HashMap。从前文可以知道HashMap在一开始初始化的时候会返回一个空的table并且thershold为0。因此第一次扩容的容量为默认值DEFAULT_INITIAL_CAPACITY也就是16。同时threshold DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR 12。 第二种指定初始容量的构造方法初始化HashMap。那么从下面源码可以看到初始容量会等于threshold接着threshold 当前的容量threshold * DEFAULT_LOAD_FACTOR。 第三种HashMap不是第一次扩容。如果HashMap已经扩容过的话那么每次table的容量以及threshold量为原有的两倍。 这边也可以引申到一个问题HashMap是先插入还是先扩容HashMap是先插入数据再进行扩容的但是如果是刚刚初始化容器的时候是先扩容再插入数据(这一点可以从putValue方法源码中看出)。 接下来是重点resize()方法 final NodeK,V[] resize() {NodeK,V[] oldTab table;int oldCap (oldTab null) ? 0 : oldTab.length;int oldThr threshold;int newCap, newThr 0;if (oldCap 0) {if (oldCap MAXIMUM_CAPACITY) {threshold Integer.MAX_VALUE;return oldTab;}else if ((newCap oldCap 1) MAXIMUM_CAPACITY oldCap DEFAULT_INITIAL_CAPACITY)newThr oldThr 1; // double threshold}else if (oldThr 0) // initial capacity was placed in thresholdnewCap oldThr;else { // zero initial threshold signifies using defaultsnewCap DEFAULT_INITIAL_CAPACITY;newThr (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);}if (newThr 0) {float ft (float)newCap * loadFactor;newThr (newCap MAXIMUM_CAPACITY ft (float)MAXIMUM_CAPACITY ?(int)ft : Integer.MAX_VALUE);}threshold newThr;SuppressWarnings({rawtypes,unchecked})NodeK,V[] newTab (NodeK,V[])new Node[newCap];table newTab;if (oldTab ! null) {for (int j 0; j oldCap; j) {NodeK,V e;if ((e oldTab[j]) ! null) {oldTab[j] null;if (e.next null)newTab[e.hash (newCap - 1)] e;else if (e instanceof TreeNode)((TreeNodeK,V)e).split(this, newTab, j, oldCap);else { // preserve orderNodeK,V loHead null, loTail null;NodeK,V hiHead null, hiTail null;NodeK,V next;do {next e.next;if ((e.hash oldCap) 0) {if (loTail null)loHead e;elseloTail.next e;loTail e;}else {if (hiTail null)hiHead e;elsehiTail.next e;hiTail e;}} while ((e next) ! null);if (loTail ! null) {loTail.next null;newTab[j] loHead;}if (hiTail ! null) {hiTail.next null;newTab[j oldCap] hiHead;}}}}}return newTab;}从resize()方法中可以看到一点:最重要的一个判断是(e.hash oldCap),从此处会将链表分成两段低位链表和高位链表低位链表的节点位置不动高位链表节点的位置是原来的位置加上老的链表的位置。 原理如下: 原table中的数据索引到新的table中要么保持位置不变要么位置 oldCap原表大小 原表索引 先放一下求余公式X % 2^n X (2^n - 1) x对2的n次方求余 length 2的n次方 原表索引 hash的后N位 length - 1 新表索引 hash的后N1位 length 1 - 1 如果还有不理解的可以看这位大神的博客:传送门 jdk1.7中为什么多线程情况下会出现死循环? 答案:直接一个传送门
http://www.dnsts.com.cn/news/132474.html

相关文章:

  • 宠物用品技术支持 东莞网站建设ps软件下载2022
  • 上海企业免费网站建设广告网站留电话不用验证码
  • 网站建设风险控制双流区规划局建设局网站
  • 网站做快捷方式wordpress淘宝客api
  • 毕业设计拼车网站的建设雨实现做男鞋的网站好
  • 合肥网站建设卫来科技wordpress模板可以添加注册会员
  • 找做废薄膜网站微信公众号小程序开发
  • 霸州住房和城乡建设厅网站淘宝指数查询工具
  • 自动做reference的网站黄骅港赶海免费最佳地点是哪里
  • 大学招生网站建设wordpress换头像
  • flash网站在线diy源码廊坊网站自助建站
  • 旧电脑怎么做网站付款网站源码
  • 营销型网站标准网页源码广告优化师是干嘛的
  • 太原网站模板公司wordpress代码高亮在线转换工具
  • 济南网站建设知识全响应网站制作
  • 网站设计应该怎么做北京住房城乡建设网站
  • 重庆网站建设方案北京住房保障建设投资中心网站
  • 怎样做班级网站培训网站视频不能拖动怎么办
  • 手机怎么搭建属于自己的网站网上做调查网站有哪些
  • 使用tag的网站wordpress引用轮播图文件
  • iis 7.0 搭建网站里水哪里做有做网站
  • 阳信网站建设网站做游戏吗
  • 宁德商城网站建设上海人才网最新招聘信息
  • 李氏牛仔网站建设风格苏州姑苏发布最新公告
  • jq 网站头部广告代码银川市住房城乡建设局网站
  • 拖拽式网站建设费用施工企业的维保技术方案
  • 国美电器如何进行网站的建设与维护手机网站制作设计
  • 公司网站设计意见长沙市做网站公司排名
  • ftp怎么做网站的备份网站设计作业多少钱
  • 四川省中国建设银行招聘信息网站甘肃兰州事件