专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

忏悔篇移除List中的元素引发的异常

  遍历集合出现的问题
  之前遇到对List进行遍历删除的时候,出现来一个ConcurrentModificationException异常,可能好多人都知道list遍历不能直接进行删除操作,但是你可能只是跟我一样知道结果,但是不知道为什么不能删除,或者说这个报错是如何产生的,那么我们今天就来研究一下。一、异常代码
  我们先看下这段代码,你有没有写过类似的代码publicstaticvoidmain(String〔〕args){ListIntegerlistnewArrayList();System。out。println(开始添加元素size:list。size());for(inti0;i100;i){list。add(i1);}System。out。println(元素添加结束size:list。size());IteratorIntegeriteratorlist。iterator();while(iterator。hasNext()){Integernextiterator。next();if(next50){list。remove(next);}}System。out。println(执行结束size:list。size());}
  毫无疑问,执行这段代码之后,必然报错,我们看下报错信息。
  我们可以通过错误信息可以看到,具体的错误是在checkForComodification这个方法产生的。二、ArrayList源码分析
  首先我们看下ArrayList的iterator这个方法,通过源码可以发现,其实这个返回的是ArrayList内部类的一个实例对象。publicIteratorEiterator(){returnnewItr();}
  我们看下Itr类的全部实现。privateclassItrimplementsIteratorE{intcursor;indexofnextelementtoreturnintlastRet1;indexoflastelementreturned;1ifnosuchintexpectedModCountmodCount;Itr(){}publicbooleanhasNext(){returncursor!size;}SuppressWarnings(unchecked)publicEnext(){checkForComodification();inticursor;if(isize)thrownewNoSuchElementException();Object〔〕elementDataArrayList。this。elementData;if(ielementData。length)thrownewConcurrentModificationException();cursori1;return(E)elementData〔lastReti〕;}publicvoidremove(){if(lastRet0)thrownewIllegalStateException();checkForComodification();try{ArrayList。this。remove(lastRet);cursorlastRet;lastRet1;expectedModCountmodCount;}catch(IndexOutOfBoundsExceptionex){thrownewConcurrentModificationException();}}OverrideSuppressWarnings(unchecked)publicvoidforEachRemaining(Consumerlt;?superEconsumer){Objects。requireNonNull(consumer);finalintsizeArrayList。this。size;inticursor;if(isize){return;}finalObject〔〕elementDataArrayList。this。elementData;if(ielementData。length){thrownewConcurrentModificationException();}while(i!sizemodCountexpectedModCount){consumer。accept((E)elementData〔i〕);}updateonceatendofiterationtoreduceheapwritetrafficcursori;lastReti1;checkForComodification();}finalvoidcheckForComodification(){if(modCount!expectedModCount)thrownewConcurrentModificationException();}}
  参数说明:
  cursor:下一次访问的索引;
  lastRet:上一次访问的索引;
  expectedModCount:对ArrayList修改次数的期望值,初始值为modCount;
  modCount:它是AbstractList的一个成员变量,表示ArrayList的修改次数,通过add和remove方法可以看出;
  几个常用方法:
  hasNext():publicbooleanhasNext(){returncursor!size;}
  如果下一个访问元素的下标不等于size,那么就表示还有元素可以访问,如果下一个访问的元素下标等于size,那么表示后面已经没有可供访问的元素。因为最后一个元素的下标是size()1,所以当访问下标等于size的时候必定没有元素可供访问。
  next():publicEnext(){checkForComodification();inticursor;if(isize)thrownewNoSuchElementException();Object〔〕elementDataArrayList。this。elementData;if(ielementData。length)thrownewConcurrentModificationException();cursori1;return(E)elementData〔lastReti〕;}
  注意下,这里面有两个非常重要的地方,cursor初始值是0,获取到元素之后,cursor加1,那么它就是下次索要访问的下标,最后一行,将i赋值给了lastRet这个其实就是上次访问的下标。
  此时,cursor变为了1,lastRet变为了0。
  最后我们看下ArrayList的remove()方法做了什么?publicbooleanremove(Objecto){if(onull){for(intindex0;indexsize;index)if(elementData〔index〕null){fastRemove(index);returntrue;}}else{for(intindex0;indexsize;index)if(o。equals(elementData〔index〕)){fastRemove(index);returntrue;}}returnfalse;}privatevoidfastRemove(intindex){modCount;intnumMovedsizeindex1;if(numMoved0)System。arraycopy(elementData,index1,elementData,index,numMoved);elementData〔size〕null;cleartoletGCdoitswork}
  重点:
  我们先记住这里,modCount初始值是0,删除一个元素之后,modCount自增1,接下来就是删除元素,最后一行将引用置为null是为了方便垃圾回收器进行回收。三、问题定位
  到这里,其实一个完整的判断、获取、删除已经走完了,此时我们回忆下各个变量的值:
  cursor:1(获取了一次元素,默认值0自增了1);
  lastRet:0(上一个访问元素的下标值);
  expectedModCount:0(初始默认值);
  modCount:1(进行了一次remove操作,变成了1);
  不知道你还记不记得,next()方法中有两次检查,如果已经忘记的话,建议你往上翻一翻,我们来看下这个判断:finalvoidcheckForComodification(){if(modCount!expectedModCount)thrownewConcurrentModificationException();}
  当modCount不等于expectedModCount的时候抛出异常,那么现在我们可以通过上面各变量的值发现,两个变量的值到底是多少,并且知道它们是怎么演变过来的。那么现在我们是不是清楚了ConcurrentModificationException异常产生的愿意呢!
  就是因为,list。remove()导致modCount与expectedModCount的值不一致从而引发的问题。四、解决问题
  我们现在知道引发这个问题,是因为两个变量的值不一致所导致的,那么有没有什么办法可以解决这个问题呢!答案肯定是有的,通过源码可以发现,Iterator里面也提供了remove方法。publicvoidremove(){if(lastRet0)thrownewIllegalStateException();checkForComodification();try{ArrayList。this。remove(lastRet);cursorlastRet;lastRet1;expectedModCountmodCount;}catch(IndexOutOfBoundsExceptionex){thrownewConcurrentModificationException();}}
  你看它做了什么,它将modCount的值赋值给了expectedModCount,那么在调用next()进行检查判断的时候势必不会出现问题。
  那么以后如果需要remove的话,千万不要使用list。remove()了,而是使用iterator。remove(),这样其实就不会出现异常了。publicstaticvoidmain(String〔〕args){ListIntegerlistnewArrayList();System。out。println(开始添加元素size:list。size());for(inti0;i100;i){list。add(i1);}System。out。println(元素添加结束size:list。size());IteratorIntegeriteratorlist。iterator();while(iterator。hasNext()){Integernextiterator。next();if(next50){iterator。remove();}}System。out。println(执行结束size:list。size());}
  建议:
  另外告诉大家,我们在进行测试的时候,如果找不到某个类的实现类,因为有时候一个类有超级多的实现类,但是你不知道它到底调用的是哪个,那么你就通过debug的方式进行查找,是很便捷的方法。五、总结
  其实这个问题很常见,也是很简单,但是我们做技术的就是把握细节,通过追溯它的具体实现,发现它的问题所在,这样你不仅仅知道这样有问题,而且你还知道这个问题具体是如何产生的,那么今后不论对于你平时的工作还是面试都是莫大的帮助。

巴智库巴海军再选择中国舰艇,肯定采购44艘052D型据巴基斯坦媒体报道,巴斯基坦空军获得第二批6架歼10CE战斗机,这批战斗机在8月30日交付巴基斯坦空军。在巴基斯坦空军抢在巴基斯坦日亮相歼10CE战斗机。在巴基斯坦国情阅兵日,5架美国售台武器将包括F35战机?台退役少将称台湾已有人会驾驶了美国参议院外委会通过台湾政策法案,该法案包括对台一系列的军售,因此备受全球瞩目。对此台湾退役少将于北辰在电视节目中指出,未来美国对台军售包括尖端的F35隐身战机,而且台湾现在已经有中方火力全开!联合国大会上怒斥美国,日本澳大利亚挨个被点名大家好,欢迎收看本期节目!国际局势愈发动荡,最近一段时间美国和欧洲以及美国的小弟日本澳大利亚是动作频频,他们不是忙着围剿俄罗斯,就是打压中国,对于这种只允许自己作威作福不允许他国发日本首相岸田文雄内阁支持率再创新低且不支持率首超支持率来源新华网根据日本共同社和日本经济新闻18日分别公布的最新民调结果,日本首相岸田文雄领导的内阁支持率再创新低,且不支持率首次超过支持率。共同社17日和18日进行的民调显示,岸田内阁南京最早的难民营!这家水泥厂8年未曾给日军生产一吨水泥近日,江南水泥厂举行了档案史料馆开馆暨南京化建集团党员教育基地挂牌仪式活动,为国企转型探索文旅融合走出了一条新道路。江南水泥厂始建于1935年,是当时国内规模最大设备和工艺最先进的恭喜!林昀儒32夺冠,前国乒奥运冠军担当场外,已加入日本国籍北京时间9月18日,国际乒联WTT哈萨克斯坦公开赛正在进行。目前,混双冠军已经出炉。混双决赛中,中国台北选手林昀儒陈思羽鏖战五局,总比分32战胜国乒徐海东吴洋晨,成功夺冠。随着国乒港股异动东瀛游(06882)升13日本计划10月起全面开放国门智通财经APP获悉,东瀛游(06882)日内显著大幅上扬,午盘涨幅扩大至13,股价来到年内高点附近。市场消息显示,日本政府计划从10月起全面解除入境政策限制。东瀛游主要开展赴日旅行早田希娜勇夺冠军!连赢中国日本欧洲高手,威胁不输伊藤美诚北京时间9月18日下午,乒乓球WTT哈萨克斯坦赛女单决赛拉开帷幕,22岁的国乒劲敌日本全国冠军早田希娜登场,与44岁的葡萄牙华裔老将付玉展开较量,结果前者以巨大的优势41笑到最后,人穷志不能穷,改变这3点,日子会越过越好随着时代的发展,现在的社会与过去已经有了翻天覆地的变化,贫富差距也是越来越大。每个人的事业发展,家境情况都各有不同,拉开差距的原因也有很多,除了知识文化,能力的不同之外,更重要的还尊重他人的意见头条创作挑战赛这章主要是如何避免在对方错误,或者意见不同时产生冲突,从而影响正常的沟通交流,甚至事情进度的推进。要面子是人的本性,仿佛刻在基因里,与生俱来,大彻大悟之人少之又少。因70游企H1财报透露降本增效密码削开支减投入撤项目上周,我们整理了70家上市游戏公司财报数据,从营收净利润出海等方面分析了各家的生存状态。在净利润层面,77家上市游戏公司(包括新增的B站)有过半净利润同比下滑,26家亏损,实现营收
08!姆巴佩惨败不服,打压梅西?曝要求巴黎不续约,瓦解南美帮本周开始,欧洲五大联赛和欧冠联赛进入间歇期,梅西内马尔姆巴佩三人都各自前往国家队备战世界杯。新赛季以来,巴黎圣日耳曼踢完11场各项赛事比赛,取得10胜1平保持不败,离不开MNM组合8块腹肌太夸张!已经41岁了!他还想打NBA这身材真是绝了!41岁的乔约翰逊近照曝出,8块腹肌明显,一身的腱子肉!图片中单打乔正在进行一系列的瑜伽锻炼,没想到40多岁的年纪还能把身材保持得这么好,当然了更重要的还是要有一颗自常吃西红柿究竟有何功效?生吃和熟吃哪个更养生?一文科普分析西红柿是一种非常多见的蔬果,含有大量对人体有益的物质,而且由于果肉多汁口感也比较好,很多人会将西红柿当成水果来食用。那么,西红柿的营养到底有多高呢?一大量果酸促消化在西红柿当中含有精华液适合什么年龄的人用?有什么功效?精华液属于密集滋养型的护肤品,适合20岁以上的人群。目前,市面上的精华液主要分为以下三种功效抗初老抗氧化美白淡斑。很多品牌的精华液会同时兼具多种功效。1抗初老类精华液首先,抗初老类胃有火口臭肝有火失眠肺有火咳嗽常备4种中成药祛一身之火大家好,我是刘医生。你有没有这种情况?经常感觉咽喉干痛,鼻子里面也总是热烘烘的,还经常长口腔溃疡,流鼻血,牙痛等症状。那你可能是上火了,俗话说火在肝里失眠,火在胃里口臭火在肺里咳嗽肝是哑巴,胃是喇叭,肝不好,胃会告诉你,一个中成药,肝胃同治大家好,我是沈医生。有句俗话是这样说得肝是哑巴,胃是喇叭,你听过这样的说法吗?你有没有发现,平时经常胃疼,打嗝反酸,消化不良,肚子发胀,口气重,吃了一些胃药会好转,但是药一停,症状坐月子是一种养生方法,既可以调理产妇身体,也可以辅助治疗疾病坐月子,是我国传统的一种养生方法。其主要功能是调养气血调理阴阳调理脏腑。在中医学理论中,它既可以用于产妇调理身体虚弱等症状,也可以用来辅助治疗某些疾病,如月经不调痛经产后病(俗称月它是秋季第一大补之物!经常喝一碗,养胃又滋阴秋进补是秋季养生的重头戏,经过炎夏酷热天气的消耗,不少人都有脾胃功能减弱的现象。如何能在不加重脾胃负担的同时又起到滋阴补益的效果?粥是秋补佳品札记中有仲秋之月养衰老,授几杖行,糜粥洋葱是血管清道夫,降血压?错了!提醒这3种食物都不能降血压55岁的胡叔,经营着自己的便利店,日子清闲又自在,美中不足的是几年前检查出患有高血压,不能胡乱饮食,很多美味都无法享受,这也成了胡叔的心病。偶然一次,胡叔听说洋葱可以降血压,于是胡心肌炎最怕的三种食物心肌炎是指心肌细胞基质和血管的炎症或变性导致,心肌炎的原发性较低,一般主要是续发于其他的疾病。心肌炎患者一般可在任何年龄段发作,尤其对于年轻人而言。如不加紧治疗,就会引起心肌炎后遗一种常见病,秋季更要注意咽部干痒胀,有异物感,咯不出,吞不下,说多几句话便感觉嗓子像要肿起来,吃点辛辣刺激食物情况更是加剧,诸如此类。如果你有上述症状,那么很有可能,你有慢性咽炎。这是一种常见病,多发于成
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网