日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

switch 的性能提升了 3 倍,我只用了这一招!

發(fā)布時(shí)間:2025/3/11 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 switch 的性能提升了 3 倍,我只用了这一招! 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

這是我的第 190?期分享

作者 | 王磊

來(lái)源 |?Java中文社群(ID:javacn666)?

分享?| Java中文社群(ID:javacn666)

上一篇《if快還是switch快?解密switch背后的秘密》我們測(cè)試了 if 和 switch 的性能,得出了要盡量使用 switch 的結(jié)論,因?yàn)樗男时?if 高很多,具體原因點(diǎn)擊上文連接查看。

既然 switch 如此有魅力,那么有沒有更好的方法,讓 switch 變得更快一些呢

答案是有的,不然本文就不會(huì)誕生了不是?

在上篇 if 和 switch 性能對(duì)比的文章中有讀者問到:String 類型的 switch 性能是否也比 if 高?先說答案,String 類型的條件判斷 switch 的性能依舊比 if 好

口說無(wú)憑,先舉個(gè)????,測(cè)試代碼如下:

import?org.openjdk.jmh.annotations.*; import?org.openjdk.jmh.infra.Blackhole; import?org.openjdk.jmh.runner.Runner; import?org.openjdk.jmh.runner.RunnerException; import?org.openjdk.jmh.runner.options.Options; import?org.openjdk.jmh.runner.options.OptionsBuilder;import?java.util.concurrent.TimeUnit;@BenchmarkMode(Mode.AverageTime)?//?測(cè)試完成時(shí)間 @OutputTimeUnit(TimeUnit.NANOSECONDS) @Warmup(iterations?=?2,?time?=?1,?timeUnit?=?TimeUnit.SECONDS)?//?預(yù)熱?2?輪,每次?1s @Measurement(iterations?=?5,?time?=?3,?timeUnit?=?TimeUnit.SECONDS)?//?測(cè)試?5?輪,每次?3s @Fork(1)?//?fork?1?個(gè)線程 @State(Scope.Thread)?//?每個(gè)測(cè)試線程一個(gè)實(shí)例 public?class?SwitchOptimizeByStringTest?{static?String?_STR?=?"Java中文社群";public?static?void?main(String[]?args)?throws?RunnerException?{//?啟動(dòng)基準(zhǔn)測(cè)試Options?opt?=?new?OptionsBuilder().include(SwitchOptimizeByStringTest.class.getSimpleName())?//?要導(dǎo)入的測(cè)試類.build();new?Runner(opt).run();?//?執(zhí)行測(cè)試}@Benchmarkpublic?void?switchTest(Blackhole?blackhole)?{String?s1;switch?(_STR)?{case?"java":s1?=?"java";break;case?"mysql":s1?=?"mysql";break;case?"oracle":s1?=?"oracle";break;case?"redis":s1?=?"redis";break;case?"mq":s1?=?"mq";break;case?"kafka":s1?=?"kafka";break;case?"rabbitmq":s1?=?"rabbitmq";break;default:s1?=?"default";break;}//?為了避免?JIT?忽略未被使用的結(jié)果計(jì)算,可以使用?Blackhole#consume?來(lái)保證方法被正常執(zhí)行blackhole.consume(s1);}@Benchmarkpublic?void?ifTest(Blackhole?blackhole)?{String?s1;if?("java".equals(_STR))?{s1?=?"java";}?else?if?("mysql".equals(_STR))?{s1?=?"mysql";}?else?if?("oracle".equals(_STR))?{s1?=?"oracle";}?else?if?("redis".equals(_STR))?{s1?=?"redis";}?else?if?("mq".equals(_STR))?{s1?=?"mq";}?else?if?("kafka".equals(_STR))?{s1?=?"kafka";}?else?if?("rabbitmq".equals(_STR))?{s1?=?"rabbitmq";}?else?{s1?=?"default";}//?為了避免?JIT?忽略未被使用的結(jié)果計(jì)算,可以使用?Blackhole#consume?來(lái)保證方法被正常執(zhí)行blackhole.consume(s1);} }

特殊說明:本文使用的是 Oracle 官方提供的性能測(cè)試工具 JMH(Java Microbenchmark Harness,JAVA 微基準(zhǔn)測(cè)試套件)進(jìn)行測(cè)試的。

以上代碼測(cè)試的結(jié)果如下:


從 Score 列(平均完成時(shí)間)可以看出 switch 的性能依舊比 if 的性能要高。

備注:本文的測(cè)試環(huán)境為:JDK 1.8 / Mac mini (2018) / Idea 2020.1

switch 性能優(yōu)化

我們知道在 JDK 1.7 之前 switch 是不支持 String 的,實(shí)際上 switch 只支持 int 類型

在 JDK 1.7 中的 String 類型,其實(shí)在編譯的時(shí)候會(huì)使用 hashCode 來(lái)作為 switch 的實(shí)際值,以上 switch 判斷字符串的代碼,編譯為字節(jié)碼實(shí)際結(jié)果如下:

public?static?void?switchTest()?{String?var1?=?_STR;byte?var2?=?-1;switch(var1.hashCode())?{case?-1008861826:if?(var1.equals("oracle"))?{var2?=?2;}break;case?-95168706:if?(var1.equals("rabbitmq"))?{var2?=?6;}break;case?3492:if?(var1.equals("mq"))?{var2?=?4;}break;case?3254818:if?(var1.equals("java"))?{var2?=?0;}break;case?101807910:if?(var1.equals("kafka"))?{var2?=?5;}break;case?104382626:if?(var1.equals("mysql"))?{var2?=?1;}break;case?108389755:if?(var1.equals("redis"))?{var2?=?3;}}//?忽略其他代碼... }

知道了 switch 實(shí)現(xiàn)的本質(zhì),那么優(yōu)化就變得比較簡(jiǎn)單了。

從以上的字節(jié)碼可以看出,如果要優(yōu)化 switch 只需要把 String 類型變成 int 類型就可以了,這樣就剩了每個(gè) case 中進(jìn)行 if 判斷的性能消耗,最終的優(yōu)化代碼如下:

public?void?switchHashCodeTest()?{String?s1;switch?(_STR.hashCode())?{case?3254818:s1?=?"java";break;case?104382626:s1?=?"mysql";break;case?-1008861826:s1?=?"oracle";break;case?108389755:s1?=?"redis";break;case?3492:s1?=?"mq";break;case?101807910:s1?=?"kafka";break;case?-95168706:s1?=?"rabbitmq";break;default:s1?=?"default";break;} }

此時(shí)我們使用 JMH 進(jìn)行實(shí)際的測(cè)試,測(cè)試代碼如下:

import?org.openjdk.jmh.annotations.*; import?org.openjdk.jmh.infra.Blackhole; import?org.openjdk.jmh.runner.Runner; import?org.openjdk.jmh.runner.RunnerException; import?org.openjdk.jmh.runner.options.Options; import?org.openjdk.jmh.runner.options.OptionsBuilder;import?java.util.concurrent.TimeUnit;@BenchmarkMode(Mode.AverageTime)?//?測(cè)試完成時(shí)間 @OutputTimeUnit(TimeUnit.NANOSECONDS) @Warmup(iterations?=?2,?time?=?1,?timeUnit?=?TimeUnit.SECONDS)?//?預(yù)熱?2?輪,每次?1s @Measurement(iterations?=?5,?time?=?3,?timeUnit?=?TimeUnit.SECONDS)?//?測(cè)試?5?輪,每次?3s @Fork(1)?//?fork?1?個(gè)線程 @State(Scope.Thread)?//?每個(gè)測(cè)試線程一個(gè)實(shí)例 public?class?SwitchOptimizeByStringTest?{static?String?_STR?=?"Java中文社群";public?static?void?main(String[]?args)?throws?RunnerException?{//?啟動(dòng)基準(zhǔn)測(cè)試Options?opt?=?new?OptionsBuilder().include(SwitchOptimizeByStringTest.class.getSimpleName())?//?要導(dǎo)入的測(cè)試類.build();new?Runner(opt).run();?//?執(zhí)行測(cè)試}@Benchmarkpublic?void?switchHashCodeTest(Blackhole?blackhole)?{String?s1;switch?(_STR.hashCode())?{case?3254818:s1?=?"java";break;case?104382626:s1?=?"mysql";break;case?-1008861826:s1?=?"oracle";break;case?108389755:s1?=?"redis";break;case?3492:s1?=?"mq";break;case?101807910:s1?=?"kafka";break;case?-95168706:s1?=?"rabbitmq";break;default:s1?=?"default";break;}//?為了避免?JIT?忽略未被使用的結(jié)果計(jì)算,可以使用?Blackhole#consume?來(lái)保證方法被正常執(zhí)行blackhole.consume(s1);}@Benchmarkpublic?void?switchTest(Blackhole?blackhole)?{String?s1;switch?(_STR)?{case?"java":s1?=?"java";break;case?"mysql":s1?=?"mysql";break;case?"oracle":s1?=?"oracle";break;case?"redis":s1?=?"redis";break;case?"mq":s1?=?"mq";break;case?"kafka":s1?=?"kafka";break;case?"rabbitmq":s1?=?"rabbitmq";break;default:s1?=?"default";break;}//?為了避免?JIT?忽略未被使用的結(jié)果計(jì)算,可以使用?Blackhole#consume?來(lái)保證方法被正常執(zhí)行blackhole.consume(s1);}@Benchmarkpublic?void?ifTest(Blackhole?blackhole)?{String?s1;if?("java".equals(_STR))?{s1?=?"java";}?else?if?("mysql".equals(_STR))?{s1?=?"mysql";}?else?if?("oracle".equals(_STR))?{s1?=?"oracle";}?else?if?("redis".equals(_STR))?{s1?=?"redis";}?else?if?("mq".equals(_STR))?{s1?=?"mq";}?else?if?("kafka".equals(_STR))?{s1?=?"kafka";}?else?if?("rabbitmq".equals(_STR))?{s1?=?"rabbitmq";}?else?{s1?=?"default";}//?為了避免?JIT?忽略未被使用的結(jié)果計(jì)算,可以使用?Blackhole#consume?來(lái)保證方法被正常執(zhí)行blackhole.consume(s1);} }

以上代碼測(cè)試的結(jié)果如下:


從以上結(jié)果可以看出,String 類型的 switch 判斷,經(jīng)過優(yōu)化之后,性能提升了 2.4 倍,可謂效果顯著。

注意事項(xiàng)

以上的 switch 優(yōu)化是基于 String 類型的,同時(shí)我們需要注意 hashCode 重復(fù)的問題,例如對(duì)于字符串“Aa”和“BB”來(lái)說,他們的 hashCode 都是 2112,因此在優(yōu)化是需要注意此類問題,也就是說我們使用 hashCode 時(shí),必須保證判斷添加的值是已知的,并且最好不要出現(xiàn) hashCode 重復(fù)的問題,如果出現(xiàn)此類問題,我們的解決方案是在 case 中進(jìn)行判斷并賦值。

其他優(yōu)化手段

我們本文重點(diǎn)討論的是 switch 性能優(yōu)化的方案,當(dāng)然如果處于性能考慮,我們還可以使用更加高效的替代方案,例如集合或者是枚舉,詳見我的另一篇文章《9個(gè)小技巧讓你的 if else看起來(lái)更優(yōu)雅》。

總結(jié)

通過本文我們知道?switch 本質(zhì)上只支持 int 類型的條件判斷,即使是 JDK 1.7 中的 String 類型,最終編譯的時(shí)候還是會(huì)被轉(zhuǎn)化為 hashCode(int)進(jìn)行判斷。但因?yàn)榫幾g成字節(jié)碼后會(huì)在 case 中使用 if equals 進(jìn)行比較,所以性能并不算太高(只比 if 高一點(diǎn)點(diǎn)),因此我們可以直接把 String 轉(zhuǎn)化成 int 類型進(jìn)行比較,從而避免在 case 中進(jìn)行 if equals 判斷的性能消耗,這樣就大大的提升 switch 的性能,但需要注意的是,有些 key 值的 hashCode 是相同的,因此在優(yōu)化時(shí)需要提前規(guī)避。

最后的話

原創(chuàng)不易,如果覺得本文對(duì)你有用,請(qǐng)隨手點(diǎn)擊一個(gè)「」,這是對(duì)作者最大的支持與鼓勵(lì),謝謝你。

if快還是switch快?解密switch背后的秘密

HashMap 的 7 種遍歷方式與性能分析!「修正篇」

關(guān)注公眾號(hào)發(fā)送”進(jìn)群“,老王拉你進(jìn)讀者群。

總結(jié)

以上是生活随笔為你收集整理的switch 的性能提升了 3 倍,我只用了这一招!的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 黑人中文字幕一区二区三区 | 欧美性受xxx黑人xyx性爽 | 欧美激情网站 | www.五月婷| 夜夜爽av福利精品导航 | 亚洲天堂视频网 | 欧美 日韩 国产 精品 | 欧美特级特黄aaaaaa在线看 | 日韩视频一区在线观看 | 婷婷视频网 | 小柔好湿好紧太爽了国产网址 | 超碰三级 | av资源站最新av | 国产又粗又猛又黄又爽无遮挡 | 色婷婷久久久亚洲一区二区三区 | 性生生活大片又黄又 | 97在线影院 | 久久国内视频 | 男人操女人下面视频 | 另类小说色 | 99久久人妻精品免费二区 | 99这里| 久久精品久久国产 | 全毛片| 色综合天天综合综合国产 | av不卡在线 | 亚洲精品a级 | www.youjizz国产| 日韩av电影网 | 国产精品午夜久久 | 精品久久影视 | 丰满圆润老女人hd | 国产91精品欧美 | 一区二区三区高清不卡 | 亚洲一区二区偷拍 | 日本成人在线视频网站 | 亚洲熟妇毛茸茸 | 国产精自产拍久久久久久蜜 | 狠狠躁夜夜躁人人爽天天高潮 | 欧美日韩一区二区三区在线播放 | 国产成人激情视频 | av东方在线| 浪潮av网站 | 色悠悠av | 免费无码一区二区三区 | 久久久久麻豆v国产精华液好用吗 | 精品98| 少妇高潮一区二区三区 | 美女扣逼喷水视频 | 天堂国产一区二区三区 | 日韩成人专区 | 天天摸日日摸 | 亚洲欧洲精品一区 | 青青青青操 | 国产乱淫av片杨贵妃 | 美女大黄动图 | 亚洲欧美国产精品久久久久久久 | 国产成人精品网站 | 四虎成人av| 91午夜在线| 欧美精品一区二 | 色呦呦视频在线观看 | 天堂av免费看 | 一区二区三区有限公司 | 91国视频| 中国av一级片 | 国产精品污 | julia一区二区三区在线观看 | 伊人婷婷在线 | 成年人网站在线观看视频 | 久久91亚洲精品中文字幕奶水 | 久久久久不卡 | 特级西西人体 | 国产黄色免费网站 | 国产精品短视频 | 国产日产精品一区二区三区四区 | 国产精品免费一区二区三区四区 | 国产96在线 | 亚洲 | 国产清纯白嫩初高中在线观看性色 | 4438x全国最大成人网 | 中文字幕有码在线观看 | 五月天福利视频 | 久久成人免费 | 浪漫樱花动漫在线观看免费 | 黄色免费大片 | 午夜精品久久久久久久99 | 中国男女全黄大片 | 久久久二区 | 99热热99 | 少妇高潮av | 不卡中文 | 日日夜夜网站 | www.国产一区二区 | 97精品一区二区 | 理论片一区 | 成人av动漫在线观看 | 青娱乐在线视频观看 | 麻豆出品| 青青青草视频在线观看 |