陣列是 Java 最底層的容器,java.util.Arrays (JDK 內建) 與 org.apache.commons.lang3.ArrayUtils (第三方神器) 覆蓋 99% 日常操作。本文系統整理宣告、初始化、遍歷、填充、排序、複製、查找、合併、反轉、移除、轉 List/Stream,附代碼範例與效能建議。
// 一維
int[] a1 = new int[5]; // 預設值 0
int[] a2 = {1,2,3,4,5}; // 簡寫
int[] a3 = new int[]{1,2,3,4,5}; // 顯式
// 多維 (不規則陣列)
int[][] matrix = new int[3][];
matrix[0] = new int[2];
matrix[1] = new int[4];
matrix[2] = new int[1];
toString(arr) | 除錯輸出 [1, 2, 3] | System.out.println(Arrays.toString(arr)); |
| deepToString(arr) | 多維陣列除錯 | Arrays.deepToString(matrix) |
| fill(arr, val) | 全量填充 | Arrays.fill(arr, -1); |
| fill(arr, from, to, val) | 區間填充 [from, to) | Arrays.fill(arr, 1, 4, 9); |
| sort(arr) | 自然順序排序 (基本型別 Dual-Pivot QuickSort, 物件 TimSort) | Arrays.sort(arr); |
| sort(arr, from, to) | 區間排序 | Arrays.sort(arr, 0, 3); |
| sort(arr, Comparator) | 自定義比較器 | Arrays.sort(strArr, String.CASE_INSENSITIVE_ORDER); |
| parallelSort(arr) | 並行排序 (ForkJoinPool, 大陣列更快) | Arrays.parallelSort(largeArr); |
| binarySearch(arr, key) | 二分查找 (前提已排序) | int idx = Arrays.binarySearch(arr, 5); |
| copyOf(arr, newLen) | 複製並調整長度 | int[] b = Arrays.copyOf(a, 10); |
| copyOfRange(arr, from, to) | 複製區間 [from, to) | int[] sub = Arrays.copyOfRange(a, 1, 4); |
| equals(arr1, arr2) | 內容逐元素比較 | Arrays.equals(a, b) |
| deepEquals(arr1, arr2) | 多維/巢狀內容比較 | Arrays.deepEquals(m1, m2) |
| mismatch(arr1, arr2) | 返回首個不相同索引 (Java 9+) | int i = Arrays.mismatch(a, b); |
| stream(arr) | 轉 IntStream/Stream | Arrays.stream(arr).filter(x > 3).toArray(); |
| spliterator(arr) | 產生 Spliterator | 供 Stream/並行處理 |
| setAll(arr, generator) | 產生器函數填充 (Java 8+) | Arrays.setAll(arr, i -> i * 2); |
| parallelSetAll(arr, generator) | 並行產生器填充 | 大陣列初始化加速 |
// 依賴: implementation 'org.apache.commons:commons-lang3:3.14.0'
// 合併
int[] combined = ArrayUtils.addAll(arr1, arr2); // 兩個
int[] combined3 = ArrayUtils.addAll(arr1, arr2, arr3); // 多個
// 在指定索引插入元素 (回傳新陣列)
int[] inserted = ArrayUtils.insert(0, arr, 99); // 頭部插入
int[] inserted2 = ArrayUtils.insert(arr.length, arr, 99); // 尾部追加
// 移除元素 (回傳新陣列)
int[] removed = ArrayUtils.remove(arr, 2); // 移除索引 2
int[] removedVal = ArrayUtils.removeElement(arr, 5); // 移除首個值為 5
// 反轉 (原地修改)
ArrayUtils.reverse(arr); // [3,2,1]
// 交換兩索引元素 (原地)
ArrayUtils.swap(arr, 0, arr.length - 1);
// 判斷包含
boolean has = ArrayUtils.contains(arr, 3); // O(n)
boolean hasAll = ArrayUtils.containsAll(arr, new int[]{1,2});
// 陣列轉 List (可變)
List list = new ArrayList<>(Arrays.asList(ArrayUtils.toObject(arr)));
// 或 Stream
List list2 = Arrays.stream(arr).boxed().collect(Collectors.toList());
// 子陣列 (視圖,不複製) - Java 9+ Arrays.copyOfRange 會複製
// ArrayUtils.subarray(arr, 1, 3) 返回新陣列
int[] distinct = Arrays.stream(arr).distinct().toArray(); // Stream (Java 8+)
// 或 LinkedHashSet
int[] distinct2 = new LinkedHashSet<>(Arrays.asList(ArrayUtils.toObject(arr)))
.stream().mapToInt(Integer::intValue).toArray();
int[] primitive = {1,2,3};
Integer[] boxed = ArrayUtils.toObject(primitive); // [1,2,3]
int[] unboxed = ArrayUtils.toPrimitive(boxed); // [1,2,3]
// 手動 Stream
Integer[] boxed2 = Arrays.stream(primitive).boxed().toArray(Integer[]::new);
int[] large = new int[10_000_000];
Arrays.parallelSetAll(large, i -> ThreadLocalRandom.current().nextInt());
Arrays.parallelSort(large); // 多核加速
// 方法參數為陣列,內部需修改 → 必須先複製
public void process(int[] input) {
int[] copy = Arrays.copyOf(input, input.length); // 防禦性複製
Arrays.sort(copy); // 不影響呼叫端原陣列
}
| 坑點 | 正確做法 |
|---|---|
Arrays.asList(arr) 傳入基本型別陣列 (如 int[]) | 返回 List (單元素為陣列);必須先 ArrayUtils.toObject 或用 Stream boxed() |
Arrays.asList 返回固定長度 List,add/remove 拋 UnsupportedOperationException | 新建 new ArrayList<>(Arrays.asList(...)) |
binarySearch 用於未排序陣列 | 結果不可預期;必須先 sort |
多維陣列用 Arrays.equals 比較 | 比較引用而非內容;必須用 deepEquals |
ArrayUtils.addAll 參數為 null | 拋 NPE;調用前判空或用 ArrayUtils.nullToEmpty |
parallelSort/parallelSetAll 發揮極致。copyOf,避免副作用污染呼叫端。掌握這兩大工具組合,即能以最少代碼完成最複雜的陣列變換任務。