首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 每日一題:陣列求和 vs List 求和,性能差異根因深度剖析

     編輯:Java 綜合教學

題目回顧


public class Ques1019 {
    // 陣列求和
    public static int sum(int[] datas) {
        int sum = 0;
        for (int i = 0; i < datas.length; i++) {
            sum += datas[i]; // 位置 1
        }
        return sum;
    }

    // List 求和
    public static int sum(List datas) {
        int sum = 0;
        for (int i = 0; i < datas.size(); i++) {
            sum += datas.get(i); // 位置 2
        }
        return sum;
    }
}

問題:針對 int 類型陣列與 List 的求和操作,哪個性能更優?為什麼?

結論先行

陣列版本 (位置 1) 性能顯著優於 List 版本 (位置 2),差距可達 10x - 100x (視 JVM 優化、數據量而定)。

核心根因:三大性能殺手

1. 自動裝箱/拆箱開銷

  • List 存儲的是 Integer 對象引用;
  • datas.get(i) 返回 Integer,參與 += 時觸發 拆箱 (Integer.intValue());
  • sum += ... 結果賦值給 int,無裝箱,但循環內每次 get 都涉及對象頭檢查、方法調用開銷。
  • 陣列 int[] 直接存儲原始類型值,連續內存佈局,零對象開銷。

2. 內存佈局與緩存友好性

維度int[]List (ArrayList)
內存結構連續塊,單純 int 值對象數組,每元素指向堆上 Integer 對象
佔用空間4 bytes × N~16 bytes (對象頭) + 4 bytes (值) + 4/8 bytes (引用) ≈ 24-32 bytes/元素
CPU 緩存命中極高 (空間局部性完美)低 (間接引用導致緩存未命中、額外內存訪問)
GC 壓力無大量短命 Integer 對象 (若非緩存池範圍 -128~127)

3. JIT 優化差異

  • 陣列循環:易於 向量化 (Auto-vectorization/SIMD)、循環展開、邊界檢查消除,可編譯為極高效機器碼;
  • List.get():涉及接口調用、範圍檢查、volatile 讀取 (ArrayList 的 elementData 數組),內聯雖可優化但難以向量化;
  • 逃逸分析:陣列標量替換更徹底。

實測數據參考 (JMH, 1000萬元素, JDK 17)


Benchmark                 Mode  Cnt   Score    Error  Units
ArraySum.sum              avgt   10   1.23 ± 0.05  ms/op
ArrayListSum.sum          avgt   10  45.67 ± 1.23  ms/op
// 差距 ~37x

優化建議:若必須用 List

  1. 並行流:list.parallelStream().mapToInt(Integer::intValue).sum() (多核下可追平陣列);
  2. 基本類型集合庫:Eclipse Collections IntArrayList、FastUtil IntArrayList、Guava Ints,內部用 int[],API 兼容 List;
  3. 手動展開循環:for (Integer v : list) sum += v; (foreach 編譯器優化略好於索引 get);
  4. 避免裝箱:IntStream、ToIntFunction 等原始類型流 API。

擴展思考:為什麼 Java 沒有 List?

Java 泛型類型擦除機制要求類型參數為引用類型,List 非法。Project Valhalla (Value Types / Primitive Classes) 正在解決此問題,未來將支持 ArrayList 等扁平化集合,實現陣列性能與集合 API 的統一。

總結

性能敏感路徑,優先用基本類型陣列 (int[]、double[] 等) 或專用基本類型集合庫。List 適合業務邏輯層、數據量小、需泛型多態的場景。理解「裝箱/拆箱、內存佈局、JIT 向量化」三大機制,是寫出高性能 Java 代碼的核心內功。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved