当前位置: 首页 > 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.hkea.cn/news/14375162/

相关文章:

  • 白云网站建设价格上小学网站建设
  • Wix网站开发 工作室个人主页建站
  • 网站建设群网站logo尺寸一般多大
  • cod单页建站工具天津网络广告公司
  • 国外网站设计网页小游戏4933
  • 做网站必须会php吗作业3 主题资源网站建设
  • wordpress主题 外贸网站模板网络媒体软文案例
  • 网站建设价格差别为什么这么大项目管理软件功能
  • 专做定制网站建设猎头公司是什么
  • 椒江住房和城乡建设规划局网站丽水建设局网站
  • 杭州网站设计建立企业网站html什么意思
  • 用dw做的网站能用吗hyper cache wordpress
  • 天睦和生态建设有限公司网站wordpress登陆页
  • 织梦网站怎么居中网站页面宽度
  • 常见的导航网站有哪些公司的网站建设费用属于什么费
  • 靖江网站建设价格室内设计师网络接单
  • 示范校建设网站维护it培训机构好
  • 文明农村建设网站新沂网站开发
  • 贵阳做网站公司杭州做网站外包公司哪家好
  • 有域名有服务器怎么做网站响应式网站开发现状
  • 电影网站开发开题报告wordpress 兼职
  • 怎样克隆别人的网站一个人能建设一个公司网站吗
  • 网站 文件 上传wordpress 写文章 插件
  • 做ppt的动图下载哪些网站seo优化技术
  • 濮阳网站建设知名公司排名威联通231p做网站
  • 牙科网站模板ppt模板大全app
  • 适合个人做的网站有哪些东西吗做网站的时候网站的第一个字母怎么在网站标题前面显示 比如谷歌g一样
  • 桂林广告公司网站建设wordpress写文章500
  • 沈阳网站制作建设陕西网站制
  • 网站改版的影响互联网金融型网站开发