十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
本篇内容介绍了“HashMap底层源码是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
为江宁等地区用户提供了全套网页设计制作服务,及江宁网站建设行业解决方案。主营业务为做网站、成都网站设计、江宁网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!
final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { // tab:Node数组 // p:Node节点 // n:Node数组的总长度 // i:当前节点的下标 Node[] tab; Node p; int n, i; // 判断Node数组是否为空,如果为空并且数组长度为0,则对Node数组进行初始化 if ((tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; // 对Hash值进行位与运算,赋值给i,得出该key所在的数组下标 // 如果tab[i]是空的,那么新建一个Node并存入数组 if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null); // 以上情况都不是 else { // e: 需要修改的节点 // k: 节点的key值 Node e; K k; // 判断Node数组饿的第一个节点的Hash值是不是和Hash一致,并且在Hash一致的情况下, // 两者的Key是否一致,一直的话,将需要修改的节点变为当前节点 if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p; // 如果P节点是树节点, 将使用红黑树的形式存储e节点 else if (p instanceof TreeNode) e = ((TreeNode )p).putTreeVal(this, tab, hash, key, value); // 如果是普通节点 else { for (int binCount = 0; ; ++binCount) { // 如果遍历到最后一个节点,新建Node存储数据 // 判断他的长度是否大于链表设定长度 // 如果大于设定长度,则将链表转换为红黑树 if ((e = p.next) == null) { p.next = newNode(hash, key, value, null); if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st treeifyBin(tab, hash); break; } // 遍历的节点如果Hash值一致,key值也一致,则跳出循环 if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } } // 如果e不为空 如果onlyIfAbsent参数(覆盖更新) // 设置为true或者e的Value是null // 将e的Value修改为传入的Value // * afterNodeAccess为LinkedHashMap函数,在HashMap中没有进行任何操作 if (e != null) { // existing mapping for key V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) e.value = value; afterNodeAccess(e); return oldValue; } } ++modCount; // 如果HashMap的总长度大于设定长度,就进行resize操作 if (++size > threshold) resize(); // * afterNodeInsertion为LinkedHashMap函数,在HashMap中没有进行任何操作 afterNodeInsertion(evict); return null; }
// 对table进行初始化或者两倍扩容 final Node[] resize() { // oldTab: 数据 // oldCap: 老容量(原Node数组长度) // oldThr: 老阀值(总数据量大于阀值则扩容) // newCap, newThr: 新容量和新阀值 Node [] oldTab = table; int oldCap = (oldTab == null) ? 0 : oldTab.length; int oldThr = threshold; int newCap, newThr = 0; // 如果oldCap大于0 if (oldCap > 0) { // oldCap >= 最大的容量(1073741824) // 将全局的阀值修改为最大的Integer(2147483647) if (oldCap >= MAXIMUM_CAPACITY) { threshold = Integer.MAX_VALUE; return oldTab; } // 解释一下 newCap = oldCap << 1 和 // newCap = oldCap * 2的结果是一样, // 如果newCap < 最大容量 并且 oldCap >= 默认初始化容量(16) // 那么 newThr = oldThr * 2 else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY && oldCap >= DEFAULT_INITIAL_CAPACITY) newThr = oldThr << 1; } // 如果oldThr大于0 else if (oldThr > 0) // newCap = oldThr newCap = oldThr; // 以上情况都不是 else { // zero initial threshold signifies using defaults // newCap = 默认初始化容量 // newThr = 默认负载因子 * 默认初始化容量 newCap = DEFAULT_INITIAL_CAPACITY; newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY); } // 如果newThr 为0 if (newThr == 0) { // ft: 新的负载数量 // ft = newCap * 负载因子 float ft = (float)newCap * loadFactor; // 如果newCap < 最大容量 && ft < 最大容量 // 那么 newThr = (int) ft // 否则 newThr = 最大Integer值 newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ? (int)ft : Integer.MAX_VALUE); } // 全局的阀值修改 threshold = newThr; @SuppressWarnings({"rawtypes","unchecked"}) Node [] newTab = (Node [])new Node[newCap]; table = newTab; if (oldTab != null) { for (int j = 0; j < oldCap; ++j) { Node e; if ((e = oldTab[j]) != null) { oldTab[j] = null; if (e.next == null) newTab[e.hash & (newCap - 1)] = e; else if (e instanceof TreeNode) ((TreeNode )e).split(this, newTab, j, oldCap); else { // preserve order Node loHead = null, loTail = null; Node hiHead = null, hiTail = null; Node next; do { next = e.next; if ((e.hash & oldCap) == 0) { if (loTail == null) loHead = e; else loTail.next = e; loTail = e; } else { if (hiTail == null) hiHead = e; else hiTail.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; }
“HashMap底层源码是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注创新互联网站,小编将为大家输出更多高质量的实用文章!