范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

HashMap源码之put方法详解

  HashMap没有直接提供putVal接口给用户调用,而实提供put接口,而他通过putVal来实现插入元素。
  public V put(K key, V value) {     return putVal(hash(key), key, value, false, true); }   /**      *      * @param hash         指定参数key的哈希值      * @param key          指定参数key      * @param value        指定参数value      * @param onlyIfAbsent 如果为true,即使指定参数key在map中已经存在,也不会替换value      * @param evict        如果为false,数组table在创建模式中      * @return 如果value被替换,则返回旧的value,否则返回null。当然,可能key对应的value就是null。      */    public V put(K key, V value) {     return putVal(hash(key), key, value, false, true); }  // 参数解析:onlyIfAbsent表示,如果为true,那么将不会替换已有的值,否则替换 // evict:该参数用于LinkedHashMap,这里没有其他作用(空实现) final V putVal(int hash, K key, V value, boolean onlyIfAbsent,                    boolean evict) {     // tab是该方法中内部数组引用,p是数组中首节点,n是内部数组长度,i是key对应的索引下标     Node[] tab; Node p; int n, i;     // 第一次put的时候,table未初始化,也就是tab为空,需要扩容     if ((tab = table) == null || (n = tab.length) == 0)     	// 这里实现扩容,具体逻辑稍后分析         n = (tab = resize()).length;     // 获取指定key的对应下标的首节点并赋值给p,如果首节点为null,那么创建一个新的Node节点作为首节点     if ((p = tab[i = (n - 1) & hash]) == null)         tab[i] = newNode(hash, key, value, null);     else {         Node e; K k;         if (p.hash == hash &&             ((k = p.key) == key || (key != null && key.equals(k))))             // p此时指向的是不为null的首节点,将p赋值给e             // 如果首节点的key和要存入的key相同,那么直接覆盖value的值(在下一个if中执行的)             e = p;         else if (p instanceof TreeNode)         	// 如果首节点是红黑树的,将键值对插添加到红黑树,该方法后续分析             e = ((TreeNode)p).putTreeVal(this, tab, hash, key, value);         else {         	// 能走到这里,说明首节点和新put的的这个节点的key不一样,且该Node节点不是TreeNode类型         	// 开始需要遍历链表,如果链表中存在该键值对,直接覆盖value。         	// 如果不存在,则在末端插入键值对。然后判断链表长度是否大于等于8(其实就是遍历次数 + 1),         	// 尝试转换成红黑树。注意此处使用"尝试",因为在treeifyBin方法中还会判断         	// 当前哈希表长度是否到达64,如果达到,转换为红黑树,否则会放弃次此转换,优先扩充数组容量。             for (int binCount = 0; ; ++binCount) {             	// 当binCount = 0时,也就是第一次if判断,此时p就是首节点,p.next就是第二个节点             	// 其他情况及时链表中其他节点,当e == null的时候,也就是到达了链表的结尾                 if ((e = p.next) == null) {                 	// 新建一个Node并作为链表的最后一个节点                     p.next = newNode(hash, key, value, null);                     // 判断遍历次数是否>=7(首节点未遍历,直接从第二个节点开始遍历的,当次数为7时,说明链表长度为8)                     if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st                     	// "尝试"将链表转换为红黑树,内部还会判断哈希表长度,不一定转换成功,也许是扩容                         treeifyBin(tab, hash);                     break;                 }                 // 只要没走到上面那个if里面,说明链表没有遍历结束,如果在链表中间发现有key一样的,那么就直接将旧值替换成新值                 if (e.hash == hash &&                     ((k = e.key) == key || (key != null && key.equals(k))))                     break;                 // 将正在遍历的节点赋值给p,方便能遍历下一个节点                 p = e;             }         }         // 首节点或者链表中间替换旧值为新值的逻辑         if (e != null) { // existing mapping for key             V oldValue = e.value;             if (!onlyIfAbsent || oldValue == null)                 e.value = value;             afterNodeAccess(e);             return oldValue;         }     }     ++modCount;     if (++size > threshold)     	// 如果满足扩容条件,就扩容         resize();     afterNodeInsertion(evict);     return null; }  //链表转化为红黑树的方法 final void treeifyBin(Node[] tab, int hash) {     int n, index; Node e;     // 在这里判断是否满足扩容条件,如果满足就扩容     if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)         resize();     else if ((e = tab[index = (n - 1) & hash]) != null) {     	// 到这里开始遍历链表         TreeNode hd = null, tl = null;         do {         	// 将链表中的节点Node类型转换成为TreeNode             TreeNode p = replacementTreeNode(e, null);             if (tl == null)                 hd = p;             else {                 p.prev = tl;                 tl.next = p;             }             tl = p;         } while ((e = e.next) != null);         // TreeNode链表转换成为红黑树         if ((tab[index] = hd) != null)             hd.treeify(tab);     } }
  在JDK8之后引入了红黑树,当哈希表的桶中链表元素超过8个的时候(此时哈希表长度不小于64),会自动转换成红黑树。若桶中元素小于等于6时,树结构还原成链表形式。
  红黑树的平均查找长度是log(n),长度为8,查找长度为log(8)=3,链表的平均查长度为n/2,当长度为8时,平均查找长度为8/2=4,这才有转换成树的必要;链表长度如果是小于等于6,6/2=3,虽然速度也很快的,但是转化为树结构和生成树的时间并不会太短。以6和8来作为平衡点是因为,中间有个差值7可以防止链表和树之间频繁的转换。
  假设,如果设计成链表个数超过8则链表转换成树结构,链表个数小于8则树结构转换成链表,如果一个HashMap不停的插入、删除元素,链表个数在8左右徘徊,就会频繁的发生树转链表、链表转树,效率会很低。概括起来就是:链表:如果元素小于8个,查询成本高,新增成本低,红黑树:如果元素大于8个,查询成本低,新增成本高。

女演员曾黎出道很早为什么不能大红大紫?作为中戏的校花,与章子怡梅婷袁泉秦海潞胡静张彤李敏并称中戏八大金钗的曾黎,形象与气质不输任何一个同学,但是这么多年却始终不温不火,确实很让人意外!要知道,曾黎在八大金钗中外形是最漂英雄联盟中,哪些英雄的被动技能很鸡肋?谢邀,这里是鸽神。时至今日,英雄联盟已拥有一百四十余位英雄,越晚出的英雄其技能机制越复杂,而那些出的比较早的英雄技能机制就相对简单得多的,虽说简单不代表不好,但是很多时候会产生一些三国演义中,为啥许多敌将碰到赵云都不战而逃?这个问题首先要说一下,是不是有许多武将遇到赵云就不战而逃还真没注意过,不过遇到赵云不逃的不是顶尖高手就是头太铁,遇到这个杀人魔王还不逃命。赵云可是演义里真正的杀人魔王出场不久就在界拳手为什么要跳绳?拳击手练习跳绳益处多。拳击手搏击格斗运动员,都会练习跳绳。而跳绳对于拳击手搏击格斗运动员,是提高技艺的非常有益的锻炼项目。我们都看到过拳击手等练习跳绳的视频,那么他们为什么要练习跳中阿之战迎来世预赛转折点,国足会成为阿曼胜利的背景板吗?转折点有点过分吧,其实前四场比赛的结果已经注定了国足的死亡没有任何机会了,分数差的太多了,还能说什么啊,最多也就是赢了阿曼遮遮羞而已,也是为李铁和足协找到退路的台阶儿吧!既然这样想为什么都说当年热火个个位置都比勇士强且詹姆斯不是报团呢?这个问题本身就有两个错误了,首先,当年的热火并不是各个位置都比勇士强,有的位置还差了不少。其次,詹姆斯当年是属于报团的,这个也没有必要掩饰。勇士队与当年热火队球员对比。我们就对比两中国足球历史上有哪些职业生涯仅效力一支球队的球员?你如何评价?中国足球自从1994年职业化联赛开始以来还是有不少球员整个职业生涯只效力于一支俱乐部,践行着一个人一座城的忠诚。小编是鲁能球迷,下面就重点介绍职业生涯只效力于鲁能的山东大汉们。一宿本人教师想买个家用打印机,预算10002000,能复印,能打印,能彩印,有什么推荐嘛,谢谢各位?本人从事电脑打印机销售从业十余年,自我感觉对打印机,尤其是家用打印机有一定认识,我来说一说吧。首先根据你的用途,需要一台可以打印复印彩色文件的机器,符合此要求的打印机有两种彩色喷墨怎样选购网络机顶盒?在购买电视盒子时,需要注意些什么?还算是有些经验,来分享一下,个人觉得,买网络机顶盒需要注意以下三点1电视盒子内存要大运行内存存储这些都是直接跟是否流畅挂钩的,小内存和存储真的害人匪浅,闪退看到一半卡住总是要清理内头发偏油,用手一抠能抠下黄色油垢,用什么洗发水适合?你好,我是山宗溪,专注分享最实用最接地气的穿搭。去油的洗发水很多呀,下面我给你分享几款自己用过的品牌吧!BOTANIST日本产的沙龙洗发水,490ml容量还挺大的!洗完以后头发滑滑当兵偷用手机被抓到,会有什么后果?中国人民解放军内务条令第一百一十一条规定除工作需要并经师(旅)以上单位首长批准外,军人不得使用移动电话寻呼机等通信工具。经批准持有移动电话寻呼机的军人,在办公场所或者参加会议训练以
靖江四大工程打造工会工作升级版中工网讯据江苏工人报消息,日前,靖江市总工会明确大力实施培根铸魂赋能成长暖心惠工固本强基四大工程,打造县级工会加强年工会工作升级版。实施培根铸魂工程。带领广大工会干部认真学习宣传贯途虎养车连续八年举办轮胎节打造全网真低价让利消费者近日,由途虎养车携手德国马牌轮胎固特异邓禄普韩泰普利司通优科豪马朝阳等各大知名轮胎品牌商联合发起的2023轮胎节全面启动。今年轮胎节围绕新产品新技术新标准三大主题展开,不仅促销力度中医养生课开班!同德积极打造家门口的老年大学近日,白云区同德街老年大学以中医药文化课为主题,全年共安排7期培训课程。邀请专业医生为长者讲授中医基础饮食调节经络腧穴的认识和保健的知识。在课堂现场,主讲人陈医生结合日常生活实际,新车2。0T柴油8AT,上汽大通领地6座暴走版实拍,售价27。58万元文懂车帝原创张凯懂车帝原创产品日前,懂车帝拍摄到了2023款上汽大通领地6座暴走版。该车定位为中大型SUV,暴走版车型可以看作全系次顶配,实拍车型采用222式6座布局,动力方面搭载卢总出手了,好评率97,体验不输小米13,起售价仅3299近半年来,芯片市场大爆发,联发科也赶上了节奏,开始与高通争天下,天玑9000系列天玑8000系列都有不错的表现。不过自从骁龙8Gen2诞生后,联发科的市场所有降低。凭借强大的性能,我们要跟上中国发展的速度多家在京外企布局加大对华投资力度新华社北京3月23日电在北京经济技术开发区的比泽尔制冷技术(中国)有限公司,灰白色的生产车间内,巨大的机器轰鸣声震耳欲聋。生产线上,工人们正在对压缩机产品进行加工和装配。经过质检后测评专用的指纹浏览器是如何实现环境独立的浏览器指纹是指几乎只能通过浏览器的各种信息,如系统字体屏幕分辨率浏览器插件,无需cookie等技术,就能定位到一个用户,即使使用浏览器的隐私窗口模式,也不能匿名。Browserpr广东罕见包揽前三甲,莞佛大飞跃!2月其它省市销量表现如何?据电车资源统计,2月,新能源物流车销量为14351辆,环比1月大涨323,同比增长94。4。当月新能源物流车销往268座城市,较去年同期增加了74座城市。其中TOP5城市合计占比为贴身束腰的瑜伽裤,充满了休闲的气息,显得很大气瑜伽裤的搭配,可以随心而欲,万变不离其宗无外乎上松下紧和上松下紧。像瑜伽裤这种能在腰间束缚住的服饰,大多是上松下紧的风格。像欧美街拍博主这样扎实的上半身,能帮助衬托出修长有型的下半白天犯困,晚上失眠?用这2个穴位能够双向调治,太厉害了春天来了,很多人白天反而更易犯困打瞌睡,晚上却睡不着打鸡血一样。好多事要忙,却又什么都不想做情绪低落,总提不起精神白天犯困,晚上失眠。说的是不是你呢?那么,为什么春天人更容易白天犯为老年乘客追回看病钱的公交司机,获5000元正能量奖励长江日报大武汉客户端3月24日讯(记者王谦马慧洁)3月10日,长江日报刊发报道你们跑不了的!公交司机一声吼,为老人追回看病钱,报道发出后,公交司机郭志辉的善举获广大网友的点赞。3月