Java 陣列無原生刪除 API。本文提供四大類解決方案:**Apache Commons Lang ArrayUtils、集合轉換法、Stream API、自定義工具類**,並對比效能、適用場景與避坑指南。
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.15.0</version>
</dependency>
int[] arr = {101, 102, 103, 104, 105};
// 按索引刪除
arr = ArrayUtils.remove(arr, 2); // 刪除索引 2 → {101, 102, 104, 105}
// 按值刪除首個匹配
arr = ArrayUtils.removeElement(arr, 104); // → {101, 102, 105}
// 按值刪除所有匹配
arr = ArrayUtils.removeAll(arr, new int[]{101, 105}); // → {102}
// 物件陣列同樣支援
String[] strs = {"a", "b", "c"};
strs = ArrayUtils.remove(strs, 1); // → {"a", "c"}
public static int[] remove(int[] array, int index) {
if (index < 0 || index >= array.length) throw new IndexOutOfBoundsException();
int[] result = new int[array.length - 1];
System.arraycopy(array, 0, result, 0, index); // 前段
System.arraycopy(array, index + 1, result, index, array.length - index - 1); // 後段
return result;
}
本質:雙段 `System.arraycopy`,原生優化,無額外開銷。
Integer[] arr = {1, 2, 3, 4, 5};
List list = new ArrayList<>(Arrays.asList(arr));
list.remove(2); // 按索引
list.remove(Integer.valueOf(3)); // 按值
arr = list.toArray(new Integer[0]);
String[] arr = {"a", "b", "c", "d"};
// 過濾掉 "c"
arr = Arrays.stream(arr).filter(s -> !"c".equals(s)).toArray(String[]::new);
// 刪除索引 1(需索引輔助)
AtomicInteger idx = new AtomicInteger();
arr = Arrays.stream(arr).filter(s -> idx.getAndIncrement() != 1).toArray(String[]::new);
int[] arr = {1, 2, 3, 4, 5};
// 過濾掉 3
arr = Arrays.stream(arr).filter(x -> x != 3).toArray();
// 刪除索引 2
IntStream.range(0, arr.length)
.filter(i -> i != 2)
.map(i -> arr[i])
.toArray();
public final class ArrayUtils {
private ArrayUtils() {}
// int[]
public static int[] remove(int[] arr, int index) {
validate(arr, index);
int[] result = new int[arr.length - 1];
System.arraycopy(arr, 0, result, 0, index);
System.arraycopy(arr, index + 1, result, index, arr.length - index - 1);
return result;
}
public static int[] removeElement(int[] arr, int element) {
int index = indexOf(arr, element);
return index >= 0 ? remove(arr, index) : arr;
}
public static int[] removeAll(int[] arr, int... elements) {
Set toRemove = Arrays.stream(elements).boxed().collect(Collectors.toSet());
return Arrays.stream(arr).filter(x -> !toRemove.contains(x)).toArray();
}
private static int indexOf(int[] arr, int target) {
for (int i = 0; i < arr.length; i++) if (arr[i] == target) return i;
return -1;
}
private static void validate(int[] arr, int index) {
if (arr == null) throw new NullPointerException("array is null");
if (index < 0 || index >= arr.length) throw new IndexOutOfBoundsException("index: " + index);
}
}
public static T[] remove(T[] arr, int index) {
if (arr == null) throw new NullPointerException();
if (index < 0 || index >= arr.length) throw new IndexOutOfBoundsException();
@SuppressWarnings("unchecked")
T[] result = (T[]) Array.newInstance(arr.getClass().getComponentType(), arr.length - 1);
System.arraycopy(arr, 0, result, 0, index);
System.arraycopy(arr, index + 1, result, index, arr.length - index - 1);
return result;
}
| 方案 | 基本型別 | 物件型別 | 依賴 | 代碼量 | 效能 |
|---|---|---|---|---|---|
| ArrayUtils | ✓ 原生優化 | ✓ 泛型支援 | commons-lang3 | 最少 | 最優 |
| List 轉換 | ✗ 需裝箱 | ✓ 自然 | 無 | 中等 | 中等(裝箱開銷) |
| Stream API | ✓ IntStream | ✓ 函數式 | 無 | 中等 | 中等(Lambda 開銷) |
| 自定義工具 | ✓ 完全控制 | ✓ 泛型 | 無 | 最多 | 同 ArrayUtils |
Java 陣列刪除本質是**新建陣列 + 雙段複製**。**生產環境首選 Apache Commons Lang ArrayUtils**,零依賴場景自建工具類核心邏輯同源。理解 `System.arraycopy` 底層機制、基本型別與物件型別差異、資料結構選型原則,才能寫出高效、正確、可維護的代碼。