游戏电视苹果数码历史美丽
投稿投诉
美丽时装
彩妆资讯
历史明星
乐活安卓
数码常识
驾车健康
苹果问答
网络发型
电视车载
室内电影
游戏科学
音乐整形

Java中的5个代码性能提升技巧,最高提升近10倍

  这篇文章介绍几个Java开发中可以进行性能优化的小技巧,虽然大多数情况下极致优化代码是没有必要的,但是作为一名技术开发者,我们还是想追求代码的更小、更快,更强。如果哪天你发现程序的运行速度不尽人意,可能会想到这篇文章。
  提示:我们不应该为了优化而优化,这有时会增加代码的复杂度。
  这篇文章中的代码都在以下环境中进行性能测试。JMHversion:1。33(Java基准测试框架)VMversion:JDK17,OpenJDK64BitServerVM,17352724
  通过这篇文章的测试,将发现以下几个操作的性能差异。预先分配HashMap的大小,提高14的性能。优化HashMap的key,性能相差9。5倍。不使用Enum。values()遍历,Spring也曾如此优化。使用Enum代替String常量,性能高出1。5倍。使用高版本JDK,基础操作有25倍性能差异。
  当前文章属于Java性能分析优化系列文章,点击可以查看所有文章。
  当前文章中的测试使用JMH基准测试,相关文章:使用JMH进行Java代码性能测试。预先分配HashMap的大小
  HashMap是Java中最为常用的集合之一,大多数的操作速度都非常快,但是HashMap在调整自身的容量大小时是很慢且难以自动优化,因此我们在定义一个HashMap之前,应该尽可能的给出它的容量大小。给出size值时要考虑负载因子,HashMap默认负载因子是0。75,也就是要设置的size值要除于0。75。
  相关文章:HashMap源码分析解读
  下面使用JMH进行基准测试,测试分别向初始容量为16和32的HashMap中插入14个元素的效率。authorhttps:www。wdbyte。comState(Scope。Benchmark)Warmup(iterations3,time3)Measurement(iterations5,time3)publicclassHashMapSize{Param({14})intkeys;Param({16,32})intsize;BenchmarkpublicHashMapInteger,IntegergetHashMap(){HashMapInteger,IntegermapnewHashMap(size);for(inti0;ikeys;i){map。put(i,i);}returnmap;}}
  HashMap的初始容量是16,负责因子0。75,最多插入12个元素,再插入时就要进行扩容,所以插入14个元素过程中需要扩容一次,但是如果HashMap初始化时就给了32容量,那么最多可以承载320。7524个元素,所以插入14个元素时是不需要扩容操作的。JMHversion:1。33VMversion:JDK17,OpenJDK64BitServerVM,17352724Benchmark(keys)(size)ModeCntScoreErrorUnitsHashMapSize。getHashMap1416thrpt254825825。152323910。557opssHashMapSize。getHashMap1432thrpt256556184。664711657。679opss
  可以看到在这次测试中,初始容量为32的HashMap比初始容量为16的HashMap每秒可以多操作26次,已经有14的性能差异了。优化HashMap的key
  如果HashMap的key值需要用到多个String字符串时,把字符串作为某个类属性,然后使用这个类的实例作为key会比使用字符串拼接效率更高。
  下面测试使用两个字符串拼接作为key,和把两个字符串作为MutablePair类的属性引用,然后使用MutablePair对象作为key的运行效率差异。authorhttps:www。wdbyte。comState(Scope。Benchmark)Warmup(iterations3,time3)Measurement(iterations5,time3)publicclassHashMapKey{privateintsize1024;privateMapString,ObjectstringMap;privateMapPair,ObjectpairMap;privateString〔〕prefixes;privateString〔〕suffixes;Setup(Level。Trial)publicvoidsetup(){prefixesnewString〔size〕;suffixesnewString〔size〕;stringMapnewHashMap();pairMapnewHashMap();for(inti0;isize;i){prefixes〔i〕UUID。randomUUID()。toString();suffixes〔i〕UUID。randomUUID()。toString();stringMap。put(prefixes〔i〕;suffixes〔i〕,i);usenewStringtoavoidreferenceequalityspeedinguptheequalscallspairMap。put(newMutablePair(prefixes〔i〕,suffixes〔i〕),i);}}BenchmarkOperationsPerInvocation(1024)publicvoidstringKey(Blackholebh){for(inti0;iprefixes。length;i){bh。consume(stringMap。get(prefixes〔i〕;suffixes〔i〕));}}BenchmarkOperationsPerInvocation(1024)publicvoidpairMap(Blackholebh){for(inti0;iprefixes。length;i){bh。consume(pairMap。get(newMutablePair(prefixes〔i〕,suffixes〔i〕)));}}}
  测试结果:JMHversion:1。33VMversion:JDK17,OpenJDK64BitServerVM,17352724BenchmarkModeCntScoreErrorUnitsHashMapKey。pairMapthrpt2589295035。4366498403。173opssHashMapKey。stringKeythrpt259410641。728389850。653opss
  可以发现使用对象引用作为key的性能,是使用String拼接作为key的性能的9。5倍。不使用Enum。values()遍历
  我们通常会使用Enum。values()进行枚举类遍历,但是这样每次调用都会分配枚举类值数量大小的数组用于操作,这里完全可以缓存起来,以减少每次内存分配的时间和空间消耗。枚举类遍历测试authorhttps:www。wdbyte。comState(Scope。Benchmark)Warmup(iterations3,time3)Measurement(iterations5,time3)BenchmarkMode(Mode。AverageTime)OutputTimeUnit(TimeUnit。MILLISECONDS)publicclassEnumIteration{enumFourteenEnum{a,b,c,d,e,f,g,h,i,j,k,l,m,n;staticfinalFourteenEnum〔〕VALUES;static{VALUESvalues();}}BenchmarkpublicvoidvaluesEnum(Blackholebh){for(FourteenEnumvalue:FourteenEnum。values()){bh。consume(value。ordinal());}}BenchmarkpublicvoidenumSetEnum(Blackholebh){for(FourteenEnumvalue:EnumSet。allOf(FourteenEnum。class)){bh。consume(value。ordinal());}}BenchmarkpublicvoidcacheEnums(Blackholebh){for(FourteenEnumvalue:FourteenEnum。VALUES){bh。consume(value。ordinal());}}}
  运行结果JMHversion:1。33VMversion:JDK17,OpenJDK64BitServerVM,17352724BenchmarkModeCntScoreErrorUnitsEnumIteration。cacheEnumsthrpt2515623401。5672274962。772opssEnumIteration。enumSetEnumthrpt258597188。662610632。249opssEnumIteration。valuesEnumthrpt2514713941。570728955。826opss
  很明显使用缓存后的遍历速度是最快的,使用EnumSet遍历效率是最低的,这很好理解,数组的遍历效率是大于哈希表的。
  可能你会觉得这里使用values()缓存和直接使用Enum。values()的效率差异很小,其实在某些调用频率很高的场景下是有很大区别的,在Spring框架中,曾使用Enum。values()这种方式在每次响应时遍历HTTP状态码枚举类,这在请求量大时造成了不必要的性能开销,后来进行了values()缓存优化。
  下面是这次提交的截图:
  使用Enum代替String常量
  使用Enum枚举类代替String常量有明显的好处,枚举类强制验证,不会出错,同时使用枚举类的效率也更高。即使作为Map的key值来看,虽然HashMap的速度已经很快了,但是使用EnumMap的速度可以更快。
  提示:不要为了优化而优化,这会增加代码的复杂度。
  下面测试使用使用Enum作为key,和使用String作为key,在map。get操作下的性能差异。authorhttps:www。wdbyte。comState(Scope。Benchmark)Warmup(iterations3,time3)Measurement(iterations5,time3)publicclassEnumMapBenchmark{enumAnEnum{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z;}要查找的key的数量privatestaticintsize10000;随机数种子privatestaticintseed99;State(Scope。Benchmark)publicstaticclassEnumMapState{privateEnumMapmap;privateAnEnum〔〕values;Setup(Level。Trial)publicvoidsetup(){mapnewEnumMap(AnEnum。class);valuesnewAnEnum〔size〕;AnEnum〔〕enumValuesAnEnum。values();SplittableRandomrandomnewSplittableRandom(seed);for(inti0;isize;i){intnextIntrandom。nextInt(0,Integer。MAXVALUE);values〔i〕enumValues〔nextIntenumValues。length〕;}for(AnEnumvalue:enumValues){map。put(value,UUID。randomUUID()。toString());}}}State(Scope。Benchmark)publicstaticclassHashMapState{privateHashMapString,Stringmap;privateString〔〕values;Setup(Level。Trial)publicvoidsetup(){mapnewHashMap();valuesnewString〔size〕;AnEnum〔〕enumValuesAnEnum。values();intpos0;SplittableRandomrandomnewSplittableRandom(seed);for(inti0;isize;i){intnextIntrandom。nextInt(0,Integer。MAXVALUE);values〔i〕enumValues〔nextIntenumValues。length〕。toString();}for(AnEnumvalue:enumValues){map。put(value。toString(),UUID。randomUUID()。toString());}}}BenchmarkpublicvoidenumMap(EnumMapStatestate,Blackholebh){for(AnEnumvalue:state。values){bh。consume(state。map。get(value));}}BenchmarkpublicvoidhashMap(HashMapStatestate,Blackholebh){for(Stringvalue:state。values){bh。consume(state。map。get(value));}}}
  运行结果:JMHversion:1。33VMversion:JDK17,OpenJDK64BitServerVM,17352724BenchmarkModeCntScoreErrorUnitsEnumMapBenchmark。enumMapthrpt2522159。2321268。800opssEnumMapBenchmark。hashMapthrpt2514528。5551323。610opss
  很明显,使用Enum作为key的性能比使用String作为key的性能高出1。5倍。但是仍然要根据实际情况考虑是否使用EnumMap和EnumSet。使用高版本JDK
  String类应该是Java中使用频率最高的类了,但是Java8中的String实现相比高版本JDK,则占用空间更多,性能更低。
  下面测试String转bytes和bytes转String在Java8以及Java11中的性能开销。authorhttps:www。wdbyte。comdate20211223State(Scope。Benchmark)Warmup(iterations3,time3)Measurement(iterations5,time3)publicclassStringInJdk{Param({10000})privateintsize;privateString〔〕stringArray;privateListbyte〔〕byteList;Setup(Level。Trial)publicvoidsetup(){byteListnewArrayList(size);stringArraynewString〔size〕;for(inti0;isize;i){StringuuidUUID。randomUUID()。toString();stringArray〔i〕uuid;byteList。add(uuid。getBytes(StandardCharsets。UTF8));}}BenchmarkpublicvoidbyteToString(Blackholebh){for(byte〔〕bytes:byteList){bh。consume(newString(bytes,StandardCharsets。UTF8));}}BenchmarkpublicvoidstringToByte(Blackholebh){for(Strings:stringArray){bh。consume(s。getBytes(StandardCharsets。UTF8));}}}
  测试结果:JMHversion:1。33VMversion:JDK1。8。0151,JavaHotSpot(TM)64BitServerVM,25。151b12Benchmark(size)ModeCntScoreErrorUnitsStringInJdk。byteToString10000thrpt252396。713133。500opssStringInJdk。stringToByte10000thrpt251745。06016。945opssJMHversion:1。33VMversion:JDK17,OpenJDK64BitServerVM,17352724Benchmark(size)ModeCntScoreErrorUnitsStringInJdk。byteToString10000thrpt255711。95441。865opssStringInJdk。stringToByte10000thrpt258595。895704。004opss
  可以看到在bytes转String操作上,Java17的性能是Java8的2。5倍左右,而String转bytes操作,Java17的性能是Java8的5倍。关于字符串的操作非常基础,随处可见,可见高版本的优势十分明显。

还记得你小时候怎么过中秋节的吗?谢大圣邀请!首先祝小悟空及头条工作人员国庆中秋节日快乐!我小时的中秋节和现在差不多,俺家玉米种了辣么多,白天坐地上剥玉米棒子,弄的一嘟噜一嘟噜里,……想存一些价格大概300元左右性价比高的白酒,有何推荐?现在有一种说法,叫存钱不如存酒。《福布斯》杂志曾经评论说:2019年在欧洲的富人圈里,藏酒以万计的人比家有3辆法拉利的人自豪得多。将来显示生活品质的,不再是私人游泳池、私人健身……茅台镇酱香酒哪个牌子比较正宗?当然是53度飞天茅台。酒色微黄而透明,酱香、焦香、糊香配合谐调,口味细腻、优雅,空杯留香持久。酒花大、成串附着于杯壁、消失速度慢。色泽微黄纯正、挂杯厚、停留持久;微……降薪帮压价!维尔纳永久转会重返莱比锡,2年蓝军生涯值了2020年,维尔纳转会加盟切尔西,不过2年的蓝军生涯,围绕维尔纳的关键词就是快乐,各种打门不进,上赛季卢卡库的加盟让维尔纳的出场时间被进一步压缩,这种前提下维尔纳自然萌生了去意……5个时间序列预测的深度学习模型对比总结时间序列预测在最近两年内发生了巨大的变化,尤其是在kaiming的MAE出现以后,现在时间序列的模型也可以用类似MAE的方法进行无监督的预训练MakridakisMCom……冬季吃不腻的五道菜,有营养味道好,食材好弄,做法没难度初冬了,天气越来越冷,也是滋补的好季节。家人健康需要热量和营养,饭菜要随着季节变换来换着花样吃,即使是家常菜,也要做得有滋有味,让看着有食欲有营养,家人胃口就会打开了。我整理了……早上好,今天是2022年11月15日,星期二,农历十月廿二〔太阳〕早安今天〔太阳〕生活的舞台上,处处都有精彩。我们不必羡慕他人的位置,只需要演好自己的角色。没有蓝天的深邃,可以有白云的飘逸;没有大海的壮阔……秋天吃鱼,鲈鱼,草鱼都不如吃它!炖汤特别鲜美,益气养血还润燥最近连续下了好几天的雨,天气确实凉了。秋意渐浓,从养生来说,秋天是一个很重要的时节,也是一个需要进补的季节。秋天天气比较干燥,除了需要全方位的补水以外,营养也得跟上……秋天,少吃猪肉多吃它,简单煮一锅,补血补铁,家人常吃胃口好到了九月份,又是秋季最该进补的一个月,很多人由于气候变化,昼夜温差特别大,平常很容易气血虚弱,女性特别容易贫血,一定需要注重补血。秋季补血,一定别错过吃这菜麻婆鸳鸯豆腐,鸳鸯豆……黄晓明海边露营被偶遇,帐篷内有一女性友人,身份引发热议这个十一长假对于黄晓明来说,过得可真是充实,这大概也是他出道以来,陪家人时间最长的一个假期,不仅参加了表弟的婚礼,当了主婚人,还顺便把青岛的大街小巷全都走了一个遍。所以前……适合萌新的上分套路,中期发育掌控全场节奏影魔最开始是纯粹的物理流。当时,隐刀是一个很好的切入装备。当然,这是一个相对较早的时期。最早的上古版本飞刀是影魔的核心装置。转战DOTA2后,依旧是体力的涌入。之后,跳刀和风杖……每日Steam折扣吸血鬼幸存者风暴之城文明6四海兄弟总览:1、VampireSurvivors(史低:20)(现:20)2、风暴之城(史低:59。25)(现:59。25)3、文明6(史低:19。9)(现:19。……
去农家乐吃饭,点了一个大鱼头,是两个人把盘子端上来的,大家吃感谢邀请!大盘子的菜特别有喜庆感,尤其是朋友聚会,食欲好像一下子就被燃爆了,虽然没吃过农家乐那种两个人一起端的大盘子,但我也有印象最深的二次吃大盆菜的经历。一次是在……86年的郎酒,大概值多少钱?这个不是真正的郎酒,真正的郎酒是古蔺郎酒厂的产品。而这个是古蔺县曲酒厂的产品,这酒是浓香型酒。没有收藏价值,只有个人饮用价值。我这瓶也很满,和你的类似,朋友圈我才卖550……现在买这3款手机,又可以当钉子户了,赶紧下手吧很多人买手机想的并不是一代一换,而是用得越久越好,买一部手机,最好用个三五年,看看那些口碑好的手机,iPhone6S、小米6、华为Mate20Pro等,像这类手机,我们常常称之……为什么大多数四川妹子在外地很受欢迎?川菜,川妹,川军,四川三大标致,应该是国人都认可的。川菜,国内菜系排首位,综合了东南西北人的食欲,再加红彤彤的火锅,南北通吃,是很多人餐桌上的开胃菜。妈哟,吃的老子钱都不……外面卖的饺子皮能买吗?会不会里面有不好的添加剂,你怎么看?饺子好吃一半的原因是饺子皮。我家是东北人,吃了无数次饺子。小时候都是妈妈和面,擀皮子,我们姐妹几个包。这些年,父母年事已高,我们工作又忙,有时候会买成品饺子皮回来包。饺子煮熟以……中国最出名的面条在哪里?最出名的面条在兰州,被世人称作兰州拉面的兰州牛肉面!可谓盛名之下,声名远扬!再也没有一款中国手工面条有如此盛誉,在名声上能同他比较的,只有最乡野的手擀面了。当然方便面另当……假发假臀假肌肉,看了明星的真实一面,网友我的容貌焦虑治好了文盐焗小娱丸编辑盐焗小娱丸娱乐圈的明星那是真的需要靠脸吃饭,美女帅哥见得多了,或许自己PUA自己吧,竟然会觉得自己还不够美?!如此一来,就给自己整了点科技与狠……用啤酒花是高档啤酒?用啤酒花浸膏是低档啤酒?都不对!别搞错了啤酒花和啤酒花浸膏,那种原料生产的啤酒更值得买?别搞错了传统啤酒的原料中,除了麦芽和酵母,还有一种叫啤酒花的原料必不可少,这里所说的啤酒花并不是啤酒中丰富的泡沫,而是一种……鳝鱼汤怎么做?这里介绍一种家常的做法,汤白味美,值得尝试。一、用料黄鳝2条、生姜一大块、大蒜6瓣、料酒一勺二、黄鳝汤的做法黄鳝洗起来很麻烦,抓在手上很容易滑走,因为外表有很多的黏液。可……恭喜内马尔,不用受姆总气了!三赢操作在酝酿,搭档C罗可冲金靴目前大巴黎方面在转会窗口最后阶段居然再次传出来了,想要进行前锋买人。而且这次目标也不是别人,正是在曼联备受质疑的英格兰球星拉什福德。其实大巴黎方面对拉什福德兴趣是相当大的……国乒25人出战仅获1亚!早田希娜斩获2冠,中国记者正视差距国乒25人出战仅获1亚!早田希娜斩获2冠,中国记者:正视差距。2022年WTT哈萨克斯坦常规挑战赛已经落下帷幕了,虽然国乒有25人出战,但是只有混双徐海东吴洋晨打进了决赛,最终……做大包子用什么香辛料会香?包子是中华民族的传统美食,其皮薄馅多,特别好吃。本人就特别喜欢吃包子,无论是什么馅的,无论是小笼包还是大包子都特别喜欢。包子好不好吃,调馅是关键。老韩今天就给大家分……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网