优化arrays工具类需规避误用引发的gc压力:避免new arraylist(arrays.aslist())的冗余拷贝;慎用copyof()和stream();复用数组对象;注意sort()中引用类型比较器的无副作用设计。

优化 Arrays 工具类使用时的 GC 暂停时间和堆内存占用,关键不在工具类本身(它不直接分配大量对象),而在于它常被误用或配合低效操作,间接引发频繁对象创建、数组复制和内存膨胀。重点是规避副作用,而非调参数。
避免 Arrays.asList() 返回的不可变列表引发隐式装箱与扩容
Arrays.asList() 返回的是 Arrays$ArrayList(非 java.util.ArrayList),它只是原始数组的包装视图,不支持 add/remove。若后续误调用这些方法,会抛 UnsupportedOperationException;但更常见的是开发者为“安全使用”而立刻转成新 ArrayList:
-
问题写法:
new ArrayList(Arrays.asList(arr))—— 触发一次完整数组拷贝 + 包装对象创建,对大数组尤其昂贵 -
建议做法:如只需遍历或只读访问,直接用
Arrays.asList(arr);如需可变集合且已知大小,用new ArrayList(capacity)预分配容量,再手动添加
慎用 Arrays.copyOf() 和 Arrays.stream() 处理大数组
这两个操作都会创建新数组或中间对象,容易在循环中反复触发 Minor GC:
-
Arrays.copyOf(arr, newLength)总是分配新数组,即使newLength ;若仅需截断且原数组可复用,改用 <code>System.arraycopy()复用目标缓冲区 -
Arrays.stream(arr).filter(...).toArray()会生成中间流对象、装箱(基本类型数组)、多次扩容;对原始类型数组,优先用IntStream/LongStream等专用流,或手写 for 循环过滤+预估长度再一次性复制
复用数组对象,减少 new int[n] / new String[n] 频率
Arrays 本身不分配数组,但调用它的场景常伴随数组创建。例如缓存计算结果、批量处理分页数据时:
- 对固定尺寸的中间数组(如 1024 字节缓冲、128 元素排序暂存),考虑使用
ThreadLocal<int></int>或对象池(如 Apache Commons Pool)复用 - 避免在高频方法中写
int[] temp = new int[64];改为类字段 +Arrays.fill(temp, 0)重置,前提是线程安全可控 - 若使用 G1 或 ZGC,可配合
-XX:G1HeapRegionSize=1M(按需)降低大数组进入老年代概率,但首要仍是减少分配
用 Arrays.sort() 时注意原始类型 vs 引用类型的开销差异
排序本身不产生新对象,但不同实现影响 GC 压力:
- 原始类型(
int[],double[])走双轴快排,纯栈/堆内操作,无对象分配 - 引用类型(
String[], 自定义对象)依赖Comparable或Comparator,若比较逻辑中新建临时对象(如new StringBuilder()),就会增加 GC 负担 —— 应确保比较器无副作用、不分配 - 对超大数组排序,考虑是否真需全量排序;可用
Arrays.parallelSort()利用多核,缩短执行时间,间接减少 STW 窗口暴露机会
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











