Stream.toList()和Collectors.toList()的效能比較

2022-05-24 21:00:18

昨天給大家介紹了Java 16中的Stream增強,可以直接通過toList()來轉換成List

主要涉及下面這幾種轉換方式:

list.stream().toList();
list.stream().collect(Collectors.toList());
list.stream().collect(Collectors.toUnmodifiableList());

然後,看到有網友評論問:Stream.toList()Collectors.toList()的區別是什麼?哪個效能好?

處理結果的區別,其實上一篇文章和視訊裡都有說:

  • Stream.toList()返回的List是不可變List,不能增刪改
  • Collectors.toList()返回的是個普通的List,可以增刪改
  • Collectors.toUnmodifiableList()返回的List是不可變List,不能增刪改

而至於效能的話,今天我們就來測試一下,看看哪個效能更好。

@BenchmarkMode(Mode.All)
@Fork(1)
@State(Scope.Thread)
@Warmup(iterations = 20, time = 1, batchSize = 10000)
@Measurement(iterations = 20, time = 1, batchSize = 10000)
public class BenchmarkStreamToList {

    @Benchmark
    public List<Integer> streamToList() {
        return IntStream.range(1, 1000).boxed().toList();
    }

    @Benchmark
    public List<Integer> collectorsToList() {
        return IntStream.range(1, 1000).boxed().collect(Collectors.toList());
    }

    @Benchmark
    public List<Integer> streamToList() {
        return IntStream.range(1, 1000).boxed().toList();
    }

}

結果報告:

Benchmark                                                                                  Mode  Cnt   Score    Error  Units
BenchmarkStreamToList.collectorsToList                                                    thrpt   20  24.422 ±  0.268  ops/s
BenchmarkStreamToList.collectorsToUnmodifiableList                                        thrpt   20  22.784 ±  0.599  ops/s
BenchmarkStreamToList.streamToList                                                        thrpt   20  31.779 ±  1.732  ops/s
BenchmarkStreamToList.collectorsToList                                                     avgt   20   0.045 ±  0.006   s/op
BenchmarkStreamToList.collectorsToUnmodifiableList                                         avgt   20   0.062 ±  0.035   s/op
BenchmarkStreamToList.streamToList                                                         avgt   20   0.040 ±  0.028   s/op
BenchmarkStreamToList.collectorsToList                                                   sample  445   0.046 ±  0.002   s/op
BenchmarkStreamToList.collectorsToList:collectorsToList·p0.00                            sample        0.039            s/op
BenchmarkStreamToList.collectorsToList:collectorsToList·p0.50                            sample        0.041            s/op
BenchmarkStreamToList.collectorsToList:collectorsToList·p0.90                            sample        0.057            s/op
BenchmarkStreamToList.collectorsToList:collectorsToList·p0.95                            sample        0.073            s/op
BenchmarkStreamToList.collectorsToList:collectorsToList·p0.99                            sample        0.102            s/op
BenchmarkStreamToList.collectorsToList:collectorsToList·p0.999                           sample        0.150            s/op
BenchmarkStreamToList.collectorsToList:collectorsToList·p0.9999                          sample        0.150            s/op
BenchmarkStreamToList.collectorsToList:collectorsToList·p1.00                            sample        0.150            s/op
BenchmarkStreamToList.collectorsToUnmodifiableList                                       sample  460   0.044 ±  0.001   s/op
BenchmarkStreamToList.collectorsToUnmodifiableList:collectorsToUnmodifiableList·p0.00    sample        0.042            s/op
BenchmarkStreamToList.collectorsToUnmodifiableList:collectorsToUnmodifiableList·p0.50    sample        0.044            s/op
BenchmarkStreamToList.collectorsToUnmodifiableList:collectorsToUnmodifiableList·p0.90    sample        0.046            s/op
BenchmarkStreamToList.collectorsToUnmodifiableList:collectorsToUnmodifiableList·p0.95    sample        0.047            s/op
BenchmarkStreamToList.collectorsToUnmodifiableList:collectorsToUnmodifiableList·p0.99    sample        0.051            s/op
BenchmarkStreamToList.collectorsToUnmodifiableList:collectorsToUnmodifiableList·p0.999   sample        0.057            s/op
BenchmarkStreamToList.collectorsToUnmodifiableList:collectorsToUnmodifiableList·p0.9999  sample        0.057            s/op
BenchmarkStreamToList.collectorsToUnmodifiableList:collectorsToUnmodifiableList·p1.00    sample        0.057            s/op
BenchmarkStreamToList.streamToList                                                       sample  655   0.031 ±  0.001   s/op
BenchmarkStreamToList.streamToList:streamToList·p0.00                                    sample        0.030            s/op
BenchmarkStreamToList.streamToList:streamToList·p0.50                                    sample        0.031            s/op
BenchmarkStreamToList.streamToList:streamToList·p0.90                                    sample        0.032            s/op
BenchmarkStreamToList.streamToList:streamToList·p0.95                                    sample        0.033            s/op
BenchmarkStreamToList.streamToList:streamToList·p0.99                                    sample        0.035            s/op
BenchmarkStreamToList.streamToList:streamToList·p0.999                                   sample        0.037            s/op
BenchmarkStreamToList.streamToList:streamToList·p0.9999                                  sample        0.037            s/op
BenchmarkStreamToList.streamToList:streamToList·p1.00                                    sample        0.037            s/op
BenchmarkStreamToList.collectorsToList                                                       ss   20   0.043 ±  0.001   s/op
BenchmarkStreamToList.collectorsToUnmodifiableList                                           ss   20   0.045 ±  0.004   s/op
BenchmarkStreamToList.streamToList                                                           ss   20   0.031 ±  0.001   s/op

從報告中我們可以看到:

  • 吞吐量:streamToList > collectorsToList > collectorsToUnmodifiableList
  • 平均耗時:streamToList > collectorsToList > collectorsToUnmodifiableList
  • p0.9999耗時:streamToList > collectorsToUnmodifiableList > collectorsToList
  • 冷啟動耗時:streamToList > collectorsToList > collectorsToUnmodifiableList

所以,Stream.toList()的效能要各方面都要好於Collectors.toList()Collectors.toUnmodifiableList()

如果您學習過程中如遇困難?可以加入我們超高質量的技術交流群,參與交流與討論,更好的學習與進步!
本文收錄在了我正在連載的《Java新特性專欄》,該系列該用電子書的方式編寫,如果想要沉浸式閱讀學習的話,可以存取Web版本:https://www.didispace.com/java-features/

再放大一些資料量,試試:

@Benchmark
public List<Integer> streamToList() {
  return IntStream.range(1, 10000).boxed().toList();
}

@Benchmark
public List<Integer> collectorsToList() {
  return IntStream.range(1, 10000).boxed().collect(Collectors.toList());
}

@Benchmark
public List<Integer> streamToList() {
  return IntStream.range(1, 10000).boxed().toList();
}

結果報告:

Benchmark                                                                                  Mode  Cnt  Score   Error  Units
BenchmarkStreamToList.collectorsToList                                                    thrpt   20  2.186 ± 0.162  ops/s
BenchmarkStreamToList.collectorsToUnmodifiableList                                        thrpt   20  2.184 ± 0.042  ops/s
BenchmarkStreamToList.streamToList                                                        thrpt   20  3.538 ± 0.058  ops/s
BenchmarkStreamToList.collectorsToList                                                     avgt   20  0.426 ± 0.004   s/op
BenchmarkStreamToList.collectorsToUnmodifiableList                                         avgt   20  0.469 ± 0.016   s/op
BenchmarkStreamToList.streamToList                                                         avgt   20  0.293 ± 0.008   s/op
BenchmarkStreamToList.collectorsToList                                                   sample   58  0.448 ± 0.049   s/op
BenchmarkStreamToList.collectorsToList:collectorsToList·p0.00                            sample       0.414           s/op
BenchmarkStreamToList.collectorsToList:collectorsToList·p0.50                            sample       0.422           s/op
BenchmarkStreamToList.collectorsToList:collectorsToList·p0.90                            sample       0.458           s/op
BenchmarkStreamToList.collectorsToList:collectorsToList·p0.95                            sample       0.560           s/op
BenchmarkStreamToList.collectorsToList:collectorsToList·p0.99                            sample       1.160           s/op
BenchmarkStreamToList.collectorsToList:collectorsToList·p0.999                           sample       1.160           s/op
BenchmarkStreamToList.collectorsToList:collectorsToList·p0.9999                          sample       1.160           s/op
BenchmarkStreamToList.collectorsToList:collectorsToList·p1.00                            sample       1.160           s/op
BenchmarkStreamToList.collectorsToUnmodifiableList                                       sample   60  0.458 ± 0.004   s/op
BenchmarkStreamToList.collectorsToUnmodifiableList:collectorsToUnmodifiableList·p0.00    sample       0.447           s/op
BenchmarkStreamToList.collectorsToUnmodifiableList:collectorsToUnmodifiableList·p0.50    sample       0.455           s/op
BenchmarkStreamToList.collectorsToUnmodifiableList:collectorsToUnmodifiableList·p0.90    sample       0.471           s/op
BenchmarkStreamToList.collectorsToUnmodifiableList:collectorsToUnmodifiableList·p0.95    sample       0.482           s/op
BenchmarkStreamToList.collectorsToUnmodifiableList:collectorsToUnmodifiableList·p0.99    sample       0.492           s/op
BenchmarkStreamToList.collectorsToUnmodifiableList:collectorsToUnmodifiableList·p0.999   sample       0.492           s/op
BenchmarkStreamToList.collectorsToUnmodifiableList:collectorsToUnmodifiableList·p0.9999  sample       0.492           s/op
BenchmarkStreamToList.collectorsToUnmodifiableList:collectorsToUnmodifiableList·p1.00    sample       0.492           s/op
BenchmarkStreamToList.streamToList                                                       sample   78  0.293 ± 0.012   s/op
BenchmarkStreamToList.streamToList:streamToList·p0.00                                    sample       0.277           s/op
BenchmarkStreamToList.streamToList:streamToList·p0.50                                    sample       0.284           s/op
BenchmarkStreamToList.streamToList:streamToList·p0.90                                    sample       0.309           s/op
BenchmarkStreamToList.streamToList:streamToList·p0.95                                    sample       0.377           s/op
BenchmarkStreamToList.streamToList:streamToList·p0.99                                    sample       0.459           s/op
BenchmarkStreamToList.streamToList:streamToList·p0.999                                   sample       0.459           s/op
BenchmarkStreamToList.streamToList:streamToList·p0.9999                                  sample       0.459           s/op
BenchmarkStreamToList.streamToList:streamToList·p1.00                                    sample       0.459           s/op
BenchmarkStreamToList.collectorsToList                                                       ss   20  0.474 ± 0.133   s/op
BenchmarkStreamToList.collectorsToUnmodifiableList                                           ss   20  0.493 ± 0.099   s/op
BenchmarkStreamToList.streamToList                                                           ss   20  0.325 ± 0.056   s/op

從報告中我們可以看到

  • 吞吐量:streamToList > collectorsToList > collectorsToUnmodifiableList
  • 平均耗時:streamToList > collectorsToList > collectorsToUnmodifiableList
  • p0.9999耗時:streamToList > collectorsToUnmodifiableList > collectorsToList
  • 冷啟動耗時:streamToList > collectorsToList > collectorsToUnmodifiableList

所以,即使集合內的元素增大,Stream.toList()的效能在各方面依然都要好於Collectors下的方法。

好了,今天的分享就到這裡,你學會了嗎?

本期視訊:https://www.bilibili.com/video/BV16Y411F7Pm/

歡迎關注我的公眾號:程式猿DD。第一時間瞭解前沿行業訊息、分享深度技術乾貨、獲取優質學習資源