Java的面向?qū)ο缶幊?/a>">Java的面向?qū)ο缶幊?/a>
805
2022-05-30
實(shí)現(xiàn)Java集合迭代的高性能
一、介紹
Java開發(fā)者經(jīng)常會(huì)遇到處理集合比如ArrayList、HashSet的情況Java 8也提供了Lambda表達(dá)式和Streaming API來簡(jiǎn)化集合相關(guān)的工作。在大多數(shù)應(yīng)用場(chǎng)景下無需考慮集合迭代的性能消耗。但是在一些極端情況下比如集合包含了上百萬條記錄的情況這個(gè)時(shí)候集合迭代就需要選擇正確的姿勢(shì)否則性能會(huì)較差。
使用JMH檢查下面每段代碼片段的運(yùn)行時(shí)間。
二、forEach vs. C Style vs. Stream API
迭代是一個(gè)非常基本的功能所有的編程語言都有簡(jiǎn)單的迭代語法允許程序員在集合上運(yùn)行迭代。Stream API可以通過Collections用非常直接的方式進(jìn)行迭代。
public?List
使用forEach循環(huán)也非常簡(jiǎn)單
public?List
C style方式的迭代其代碼要冗長(zhǎng)一些但仍然非常緊湊
public?List 以上代碼的性能評(píng)分如下 Benchmark Mode Cnt Score Error Units TestLoopPerformance.forCStyle avgt 200 18.068 ± 0.074 ms/op TestLoopPerformance.forEach avgt 200 30.566 ± 0.165 ms/op TestLoopPerformance.streamMultiThread avgt 200 79.433 ± 0.747 ms/op TestLoopPerformance.streamSingleThread avgt 200 37.779 ± 0.485 ms/op 對(duì)于C style方式的迭代JVM只是簡(jiǎn)單地增加了一個(gè)整型變量它直接從內(nèi)存讀值。這使它非常快。但forEach迭代則不同根據(jù)Oracle官方文檔JVM必須把forEach轉(zhuǎn)換為迭代器并為每個(gè)數(shù)據(jù)項(xiàng)調(diào)用hasNext()。這就是為什么forEach比C style迭代慢。 forEach文檔(https://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html) 三、哪一種迭代的性能最高 我們定義測(cè)試數(shù)據(jù) @State(Scope.Benchmark) public?static?class?BenchMarkState?{ ????@Setup(Level.Trial) ????public?void?doSetup()?{ ????????for(int?i?=?0;?i?500000;?i++){ ????????????testData.add(Integer.valueOf(i)); ????????} ????} ????@TearDown(Level.Trial) ????public?void?doTearDown()?{ ????????testData?=?new?HashSet<>(500000); ????} ????public?Set Java Set同時(shí)支持Stream API和forEach循環(huán)。根據(jù)前面的測(cè)試如果我們把Set轉(zhuǎn)換為ArrayList看看性能是否有所提升。 public?List C style組合迭代的循環(huán) public?List?forCStyleWithIteration(BenchMarkState?state)?{? int?size?=?state.testData.size();? List?result?=?new?ArrayList<>(size);? Iterator?iteration?=?state.testData.iterator();? for(int?j?=?0;?j? forEach public?List 看起來代碼簡(jiǎn)潔但并不理想因?yàn)槌跏蓟疉rrayList比較消耗資源。 Benchmark Mode Cnt Score Error Units TestLoopPerformance.forCStyle avgt 200 6.013 ± 0.108 ms/op TestLoopPerformance.forCStyleWithIteration avgt 200 4.281 ± 0.049 ms/op TestLoopPerformance.forEach avgt 200 4.498 ± 0.026 ms/op HashMap (HashSet uses HashMap 結(jié)論 在集合Collections上使用Foreach和Stream API是非常便利的方法寫這樣的代碼也顯得精煉。但要記住當(dāng)系統(tǒng)需要考慮性能和穩(wěn)定性因素時(shí)就應(yīng)該改寫這些循環(huán)。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。