应用办公生活信息教育商业
投稿投诉
商业财经
汽车智能
教育国际
房产环球
信息数码
热点科技
生活手机
晨报新闻
办公软件
科学动态
应用生物
体育时事

for循环嵌套for循环,你需要懂的代码性能优化技巧!

  前言
  本篇分析的技巧点其实是比较常见的,但是最近的几次的代码评审还是发现有不少兄弟没注意到。
  所以还是想拿出来说下。正文
  是个什么场景呢?
  就是for循环里面还有for循环,然后做一些数据匹配、处理这种场景。
  我们结合实例代码来看看。
  场景示例:比如我们现在拿到两个list数据,一个是UserList集合;另一个是UserMemoList集合;
  我们需要遍历UserList,然后根据userId从UserMemoList里面取出对应这个userId的content值,做数据处理。
  代码User。java:importlombok。Data;DatapublicclassUser{privateLonguserId;privateStringname;}
  代码UserMemo。java:importlombok。Data;DatapublicclassUserMemo{privateLonguserId;privateStringcontent;}
  模拟数据集合:
  5W条user数据,3W条userMemo数据publicstaticListUsergetUserTestList(){ListUserusersnewArrayList();for(inti1;i50000;i){UserusernewUser();user。setName(UUID。randomUUID()。toString());user。setUserId((long)i);users。add(user);}returnusers;}publicstaticListUserMemogetUserMemoTestList(){ListUserMemouserMemosnewArrayList();for(inti30000;i1;i){UserMemouserMemonewUserMemo();userMemo。setContent(UUID。randomUUID()。toString());userMemo。setUserId((long)i);userMemos。add(userMemo);}returnuserMemos;}
  先看平时大家不注意的时候可能会这样去写代码处理:
  ps:其实数据量小的话,其实没多大性能差别,不过我们还是需要知道一些技巧点。
  代码:publicstaticvoidmain(String〔〕args){ListUseruserTestListgetUserTestList();ListUserMemouserMemoTestListgetUserMemoTestList();StopWatchstopWatchnewStopWatch();stopWatch。start();for(Useruser:userTestList){LonguserIduser。getUserId();for(UserMemouserMemo:userMemoTestList){if(userId。equals(userMemo。getUserId())){StringcontentuserMemo。getContent();System。out。println(模拟数据content业务处理。。。。。。content);}}}stopWatch。stop();System。out。println(最终耗时stopWatch。getTotalTimeMillis());}
  我们来看看这时候的一个耗时情况:
  相当于迭代了5W3W次
  可以看到用时是26857毫秒
  其实到这,插入个题外点,如果说每个userId在UserMemoList里面都是只有一条数据的场景。for(Useruser:userTestList){LonguserIduser。getUserId();for(UserMemouserMemo:userMemoTestList){if(userId。equals(userMemo。getUserId())){StringcontentuserMemo。getContent();System。out。println(模拟数据content业务处理。。。。。。content);}}}
  单从这段代码有没有问题,有没有优化点。
  显然是有的,因为当我们从内循环UserMemoList里面找到匹配数据的时候,没有做其他操作了。
  这样内for循环会继续下,直到跑完再进行下一轮整体循环。
  所以,仅针对这种情形,1对1的或者说我们只需要找到一个匹配项,处理完后我们应该使用break。
  我们来看看加上break的一个耗时情况:
  代码:publicstaticvoidmain(String〔〕args){ListUseruserTestListgetUserTestList();ListUserMemouserMemoTestListgetUserMemoTestList();StopWatchstopWatchnewStopWatch();stopWatch。start();for(Useruser:userTestList){LonguserIduser。getUserId();for(UserMemouserMemo:userMemoTestList){if(userId。equals(userMemo。getUserId())){StringcontentuserMemo。getContent();System。out。println(模拟数据content业务处理。。。。。。content);break;}}}stopWatch。stop();System。out。println(最终耗时stopWatch。getTotalTimeMillis());}
  耗时情况:
  可以看到从2W多毫秒变成了1W多毫秒,这个break加的很OK。
  回到我们刚才,平时需要for循环里面再for循环这种方式,可以看到耗时是2万6千多毫秒。
  那如果场景更复杂一定,是for循环里面for循环多个或者,for循环里面还有一层for循环,那这样代码耗时真的非常恐怖。
  那么接下来这个技巧点是使用map去优化:
  代码:publicstaticvoidmain(String〔〕args){ListUseruserTestListgetUserTestList();ListUserMemouserMemoTestListgetUserMemoTestList();StopWatchstopWatchnewStopWatch();stopWatch。start();MapLong,StringcontentMapuserMemoTestList。stream()。collect(Collectors。toMap(UserMemo::getUserId,UserMemo::getContent));for(Useruser:userTestList){LonguserIduser。getUserId();StringcontentcontentMap。get(userId);if(StringUtils。hasLength(content)){System。out。println(模拟数据content业务处理。。。。。。content);}}stopWatch。stop();System。out。println(最终耗时stopWatch。getTotalTimeMillis());}
  看看耗时:
  为什么这么显著的效果?
  这其实就是时间复杂度,for循环嵌套for循环,就好比循环每一个user,拿出userId需要在里面的循环从userMemolist集合里面按顺序去开盲盒匹配,拿出第一个,看看userId,拿出第二个,看看userId,一直找匹配的。
  而我们提前对userMemolist集合做一次遍历,转存储在map里面。
  map的取值效率在多数的情况下是能维持接近O(1)的,毕竟数据结构摆着,数组加链表。
  相当于拿到userId想去开盲盒的时候,根据userId这个keyhash完能直接找到数组里面的索引标记位,如果底下没链表(有的话O(logN)),直接取出来就完事了。
  然后补充一个getNode的代码注释:ImplementsMap。getandrelatedmethods。这是个Map。get的实现方法paramhashhashforkeyparamkeythekeyreturnthenode,ornullifnonefinal写死了无法更改返回Node传入查找的hash值和key键finalNodeK,VgetNode(inthash,Objectkey){tab还是哈希表first哈希表找的链表红黑树对应的头结点e代表当前节点k代表当前的keyNodeK,V〔〕tab;NodeK,Vfirst,e;intn;Kk;赋值并过滤哈希表空的长度不够的对应位置没存数据的都直接returnnullif((tabtable)!null(ntab。length)0(firsttab〔(n1)hash〕)!null){头结点就找到了hash相等值相等或者不空的key和当前节点equalsif(first。hashhashalwayscheckfirstnode((kfirst。key)key(key!nullkey。equals(k))))returnfirst;头结点不匹配没找到就就用next找if((efirst。next)!null){是不是红黑树的if(firstinstanceofTreeNode)return((TreeNodeK,V)first)。getTreeNode(hash,key);红黑树就直接调用红黑树内查找不为空或者没找到就dowhile循环do{当前节点找到了hash相等值相等或者不空的key和当前节点equalsif(e。hashhash((ke。key)key(key!nullkey。equals(k))))returne;}while((ee。next)!null);}}returnnull;}
  按照目前以JDK8的hash算法,起hash冲突的情况是非常非常少见了。
  最恶劣的情况,只有当全部key都冲突,全都分配到一个桶里面去都占用一个位置,这时候就是O(n),这种情景不需要去考虑。
  原文链接;https:mp。weixin。qq。comsYok5B9j6nbK1o3fn6TA

孩子长高有2个黄金期,一个白金期!抓牢了,轻松突破遗传身高文丨美妈很帅第3话导读:了解三个生长加速期,帮孩子把握每一个蹿高的机会!解密靶身高,预测孩子最终身高!了解每年增高速度,帮助孩子突破遗传身高!傍晚去幼儿园接儿子的时……中华传统中医中药煎煮方法及服药注意事项(收藏)中医作为中国传统医学,包含了中华民族传统的文化和思想,中医博大而精深!它的主要内容包括中医的基础理论、中医的养生方法、中医的诊疗手段等。中药煎煮方法及服药注意事项一……带3000人民币,能在泰国生活多久?游客来了才发现有惊喜准备3000元人民币,在泰国能潇洒多久呢?第一次体验过的游客表示,完全没想到,在泰国竟有如此好的体验。泰国算是东南亚最受欢迎的旅游国家,每年都要接待上千万的海外游客……50岁的女人容易显老的4个地方,看看你有吗?哈喽,大家好,我是甘老师。女人最怕听到的一个字就是老,而最担心的就是变老。为此不惜花费大价钱,用来打扮自己。但若是用错了劲,真的得不偿失,反而有种老黄瓜刷绿漆……蔡斌面临新难题,中国女排队长谁来当?三大候选人袁心玥最合适今年是巴黎奥运周期的第一年,中国女排面临着许许多多的挑战,颜妮、林莉和刘晓彤等奥运冠军相继退役,张常宁逐渐回归家庭,是否重新回到赛场目前也不明了,朱婷受手腕伤势影响,何时复出也……OOTD161112微胖女生办公室穿搭必备显瘦单品(加班篇)是的,我本周周末加班了〔尬笑〕最近广州的天气阴晴不定,周末遇到降温遇到下雨再遇到加班,宝宝心里苦,但宝宝还是要说出来〔吐血〕〔吐血〕遇到周末要加班的话,我都穿的比较……过敏性鼻炎春季高发,应该如何防范呢?今天是2022年2月20日,北京的天气还是很不错的,上午出诊的患者中,有6位患者,都是过敏性鼻炎复发,前来就诊的!春天作为过敏性鼻炎的高发季节,其温差变化大,万物复苏,植物生长……没有球星就制造球星展淑萍从平民球员中挖掘出来的悍将篮球赛场上,如同龙王爷比宝,谁的宝贝多谁赢。在WCBA,哪支队伍拥有的球星数量多,自然实力就强,争取好成绩的希望就更大。比如四川,比如内蒙古聚集了众多国手明星,这才一骑绝……医案头身困重,周身酸楚,脘闷,纳呆,呕吐,胃痛,腹泻日3次春夏养阳,秋冬养阴,出自《黄帝内经素问四气调神大论篇》,是谓春夏养阳,以养阳之生长;秋冬养阴,以养阴之收藏。盖因春生、夏长、秋收、冬藏顺应自然,方可安康。天气越热我们越不能喝冰……中国大都使用手机,为何发达国家却流行固定电话?看完你就知道了如今你家还有固定电话吗?发达国家的人固话比手机用得多?中国人上至70岁的老人,下至5岁的儿童大都使用手机,固定电话在我国早已退出神坛。而在全球5G手机市场中的普及率中中国……插上科技翅膀智慧助老让老人接轨数字化生活来源:【交汇点新闻客户端】交汇点讯爷爷,打开这个绿色式样的微信,点下这右上方的扫一扫,就可以识别二维码。我来操作一下,您看为帮助老年人更好地融入信息化时代,近日,扬州大学……陈子豪被封印?世界哥AE狙神通天带!生死狙击2冠军赛火热开打AE世界哥当年在TSG战队的一杆神狙和顶尖身法,让无数玩家有幸见识到了中国的天才少年,然而他的过早退役也成为了不少玩家心中最大的遗憾。本来以为世界哥的神狙会永远留在职业赛……
因动力电池订单量大增相关企业开始涨薪留人赶工期【CNMO新闻】随着新能源汽车的不断发展和普及,围绕这个产业的周边业务的发展也受到了较大的提升。而动力电池市场则是收益最多的对象之一,最为新能源汽车最核心的部件,动力电池的产量……日本色彩协会2023年度流行色发布!和潘通比哪个好看?hello艾瑞巴蒂你们的图图又和你们见面啦近期,日本流行色彩协会(JAFCA)公布了他们评选出来的2023年度代表色如阳光般的淡暖黄带给人们……三峡游轮华夏神女2号(重庆至宜昌)线路指南和价格分享长江三峡游轮旅游既轻松又优雅自在,每天随波而行,在山水间享受惬意时光,能够远离城市喧嚣,走近自然放松身心。今天给大家分享的是三峡游轮华夏神女2号从重庆至宜昌的线路和价格情况。一……特种兵式旅游看呆网友女子30小时往返1300公里游6景点,第点击上方新北方订阅哦!近日,一单休女子趁着周末放假坐8小时卧铺从郑州前往北京游玩一天引发热议。据女生介绍,自己下午6点下班,坐上了晚9……换脸界的7位女星杨紫景甜不算啥,陈数才是最狠的在阅读此文之前,麻烦您点击一下关注,既方便您进行讨论和分享,又能给您带来不一样的参与感,感谢您的支持〔比心〕文乔乔编辑乔乔娱乐圈里的美女真的都是天生丽质的吗?……批评平田树消极!韩瑞熙不满意比赛过程,很兴奋拿下挑战权!北京时间3月25日ONE:巅峰系列赛8中,原子量级排名第二的韩国名将韩瑞熙(HamSeoHee)与人造人18号平田树(ItsukiHirata)展开一场大战。赛前平田树表……华为撕下国产手机厂商的遮羞布,苹果不愿意看到的情况出现大家都知道,由于老美的制裁,近几年来华为的日子并不好过,从一开始的限制华为使用美技术和软件设计,到后来的限制华为采购5G芯片和限制台积电等向华为提供芯片代工服务,再到现在美国又……踏春赏花,野外露营长沙的春天有N种打开方式!长沙晚报4月1日讯(全媒体记者宁莎鸥)4月1日,周六,春暖花开。趁着周末的空闲,本地市民走出家门,外地游客纷至沓来,赏花踏青。景区里,游客摩肩接踵;在一些条件允许的开放绿地上,……以砍一刀著称的某夕夕,何以这次被人砍的血肉模糊?有没有经常接到朋友同事发来帮忙砍一刀的请求信息,不得已下载该软件的经历?广告超多,不经意点击一下就会自动下载安装、玩套路、诱导用户、假冒劣质商品等等是用户对该软件的普遍反……子宫腺肌症引起的贫血,补血只是起到缓解的作用,降低贫血子宫腺肌症引起贫血,一定要高度重视。对于子宫腺肌症的患者,一个就是月经量比较大,对月经量大来说重点就是导致的贫血。有的可能严重的血红蛋白能达到60左右,这就非常低的一种贫……315后电视投诉量排名出炉海信视频会员成重灾区中国市场电视年销量达三千万台以上,是全球最大的电视市场之一,也是各个品牌竞相角逐的舞台。如此重要且庞大的市场,非常考验电视品牌的综合能力,产品质量是否过硬、售后服务水平如何、用……48岁黄渤新剧首波口碑出炉了!观众的打分评价都一针见血别看这两年的爆款剧题材越来越小众,各种悬疑、科幻、无限流噱头十足,但真正能打开市场的还得是本身就很大众化的偶像剧、生活剧题材。春节档期间,院线电影成为近期的话题的热点,但……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网