Arrays.fill() 是 Java 中批量初始化或重置数组的首选工具,底层常优化为内存块拷贝,性能优于 for 循环;支持一维全填/区间填、二维逐行填(避免引用共享)、对象数组填引用(非新建对象),并需注意 null 安全与适用场景。

Arrays.fill() 是 Java 中批量初始化或重置数组最直接、最高效的方式,不是“能用就行”的备选方案,而是针对“统一赋值”这一明确语义的首选工具。它底层常被 JVM 优化为内存块拷贝(如 int[]),性能明显优于手写 for 循环;同时代码简洁、意图清晰,大幅降低出错概率。
一维数组:全填、局部填,一行到位
绝大多数初始化场景都落在一维数组上,Arrays.fill 提供两个核心重载:
-
全数组填充:Arrays.fill(arr, value),适用于新建后统一设默认值,比如
int[] dp = new int[1000]; Arrays.fill(dp, -1);表示“未计算”状态;String[] names = new String[50]; Arrays.fill(names, "N/A");避免 null 引用。 -
区间填充:Arrays.fill(arr, from, to, value),索引规则与 substring 一致(含头不含尾)。适合滑动窗口重置、动态规划中预设前 k 个无效值(如
Arrays.fill(dp, 0, k, Integer.MAX_VALUE))、跳过已处理头尾等场景。注意 from ≥ 0、to ≤ arr.length,否则抛 ArrayIndexOutOfBoundsException。
二维数组:逐行 fill,避开引用共享陷阱
Java 的二维数组本质是“数组的数组”,matrix[i] 存的是引用。直接 Arrays.fill(matrix, row) 会让所有行指向同一对象,改一个就全变——这是高频 Bug。
-
安全做法:用增强 for 循环逐行调用 fill,例如
for (int[] row : matrix) Arrays.fill(row, 0);。语义清楚,JVM 易优化,比双重 for 快 20–30%。 -
大规模矩阵(如 ≥1 万行):可结合并行流提速,
Arrays.stream(matrix).parallel().forEach(row -> Arrays.fill(row, -1));。16 核机器实测 10000×1000 矩阵初始化从 423 ms 降至约 58 ms,但小数组不建议,有调度开销。
对象数组:填引用不等于建新对象
Arrays.fill 对引用类型数组只复制引用,不调用构造器。这点极易被忽略:
立即学习“Java免费学习笔记(深入)”;
-
危险操作:
List<Integer>[] lists = new ArrayList[5]; Arrays.fill(lists, new ArrayList<>());→ 所有位置共用同一个 ArrayList 实例,add 一个元素,全部“看到”。 -
正确做法:需独立对象时,必须显式循环创建,例如
for (int i = 0; i < lists.length; i++) lists[i] = new ArrayList<>();。也可用Arrays.setAll(lists, i -> new ArrayList<>());,语义更函数化。 -
null 安全:对 null 数组调用 fill 会触发 NullPointerException,生产代码建议先判空,如
if (arr != null) Arrays.fill(arr, value);。
性能与选型:什么时候该用,什么时候换别的
Arrays.fill 不是万能钥匙,关键看需求是否匹配“统一值”这个前提:
- 优先用 fill:基本类型数组全/区间初始化、布尔/字符串占位符、缓存重置、算法题中快速建 dp 或 visited 数组。
-
换 Arrays.setAll:需要按索引生成不同值,比如
i*i、"ID_" + i、或依赖外部变量的逻辑。 -
静态初始化更优:数据固定且编译期可知,如
int[][] m = {{1,2},{3,4}};,零运行时成本,调试也直观。 - 避免滥用:不要为了“看起来函数式”而硬套 fill 去做本该用 stream 处理的复杂映射;也不要在小数组上盲目上并行流。


















