做爲技術人員,學習新知識是基本功課。有些知識是不得不學,有些知識是學了以後如虎添翼,Java8的Stream就是兼具二者的知識。不學看不懂,學了寫起代碼來如虎添翼。java
在上篇《Java8 Stream新特性詳解及實戰》中咱們介紹了Java8 Stream的基本使用方法,嘗試一下是否是感受很爽?當只用一行代碼就搞定最終結果時,是否是不再想用for循環一遍遍去迭代了。git
同時,你是否又看到相似《Java8 Lambda表達式和流操做如何讓你的代碼變慢5倍》這樣的文章,那麼今天就帶你們經過編寫測試程序來一探究竟,看看Stream的性能到底如何。同時,帶你們認識一個很是不錯的性能測試工具junitperf。github
先同步一下測試環境及工具信息:算法
在測試的過程當中電腦中還開了其餘不少應用,但基本上都沒進行操做。數組
基本測試方案,先初始化一個int數組,5億個隨機數。而後從這個數組中找到最小的一個數。服務器
採用三個單元測試方法來對照參考:dom
測試程序相關代碼:工具
public class StreamTest { public static int[] arr; @BeforeAll public static void init() { arr = new int[500000000]; randomInt(arr); } @JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class}) public void testIntFor() { minIntFor(arr); } @JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class}) public void testIntParallelStream() { minIntParallelStream(arr); } @JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class}) public void testIntStream() { minIntStream(arr); } private int minIntStream(int[] arr) { return Arrays.stream(arr).min().getAsInt(); } private int minIntParallelStream(int[] arr) { return Arrays.stream(arr).parallel().min().getAsInt(); } private int minIntFor(int[] arr) { int min = Integer.MAX_VALUE; for (int anArr : arr) { if (anArr < min) { min = anArr; } } return min; } private static void randomInt(int[] arr) { Random r = new Random(); for (int i = 0; i < arr.length; i++) { arr[i] = r.nextInt(); } } }
基本操做流程:經過@BeforeAll註解的init方法對數組進行隨機初始化,而後再統一執行上面三個測試方法。性能
在單元測試的方法上都有下面的註解:單元測試
@JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class})
該註釋爲junitperf提供的註解,其中duration爲持續執行這段代碼的時間,單位毫秒;warmUp預熱時間,這裏預熱1秒;reporter輸出報表格式,這裏採用HTML展現,能夠更直觀看到效果。
好上面的一切都準備好了,剩下的就是統一執行單元測試。執行結果以下三個圖。
針對基礎類型(int)操做,結果分析:
生成一個List列表,列表中隨機生成10000000個字符串,而後分別經過不一樣的方式計算得到最小的字符串。
基本操做與實驗一相同,再也不貼出代碼,直接看測試的效果圖。
針對對象(String)操做,結果分析:
生成一個List列表,列表裏面存放着1百萬個User對象。每一個對象中都包含用戶名和用戶某次運動的距離,同一用戶可在List裏包含多條運動記錄。如今經過不一樣的方式來統計用戶的總共運動了多遠距離。
基本測試思路一致,這裏只貼出基於Stream的算法的代碼,以便你們瞭解Stream的複雜對象歸約如何使用。
// 串行寫法 users.stream().collect( Collectors.groupingBy(User::getUserName, Collectors.summingDouble(User::getMeters))); // 並行寫法 users.parallelStream().collect( Collectors.groupingBy(User::getUserName, Collectors.summingDouble(User::getMeters)));
下面看測試結果的數據:
複雜對象歸約操做,結果分析:
最後推薦一下這款用起來還不錯的Java性能測試工具,GitHub地址:https://github.com/houbb/juni...。 上面有詳細的使用說明。惟一缺乏的就是數據預初始化的示例,而本篇文章的示例中已經補上了這部分缺失。
經過上面的幾組實驗對比,咱們能夠看到以下結論:
用一句話來講就是:簡單操做for循環便可,複雜操做首推Stream。
如今的Stream書寫簡單,性能不錯,若是將來JDK針對其進行優化,便同時享受了便捷和性能,何樂而不爲呢。
原文連接《Java8 Stream性能如何及評測工具推薦》