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

Java 陣列刪除指定元素完整方案:ArrayUtils、List 轉換、Stream API 與自定義工具類

     編輯:Java 相關知識

前言

Java 陣列無原生刪除 API。本文提供四大類解決方案:**Apache Commons Lang ArrayUtils、集合轉換法、Stream API、自定義工具類**,並對比效能、適用場景與避坑指南。

方案一:Apache Commons Lang ArrayUtils(推薦生產環境)

1.1 Maven 依賴


<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.15.0</version>
</dependency>

1.2 核心 API


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"}

1.3 源碼原理(ArrayUtils.remove)


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`,原生優化,無額外開銷。

方案二:集合轉換法(語義清晰,適合物件陣列)

2.1 List 除後轉回


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]);

2.2 注意事項

  • `Arrays.asList` 返回**固定長度** List,**不可增刪**,必須 `new ArrayList<>()` 包裝
  • 基本型別陣列(`int[]`)**無法**直接 `Arrays.asList`,會視為單一元素 `List`
  • 基本型別需先裝箱流式處理:`Arrays.stream(arr).boxed().collect(Collectors.toList())`

方案三:Stream API(Java 8+ 函數式風格)

3.1 物件陣列


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);

3.2 基本型別陣列


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();

3.3 效能特徵

  • 優點:語義聲明式、鏈式操作、易於並行 `parallelStream()`
  • 缺點:物件陣列裝箱/拆箱開銷、Lambda 捕獲變數開銷、小陣列比手寫慢

方案四:自定義通用工具類(零依賴、完全控制)

4.1 基本型別重載版


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);
    }
}

4.2 物件陣列泛型版


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

選型建議

  1. 企業級專案、追求穩定 → **Apache Commons Lang ArrayUtils**(經過大規模生產驗證)
  2. 輕量專案、不想引入依賴 → **自定義工具類**(複製 ArrayUtils 核心源碼)
  3. 函數式風格、需複雜過濾 → **Stream API**
  4. 一次性腳本、原型開發 → **List 轉換法**(最直觀)

避坑清單

  1. 基本型別陣列**不可**直接 `Arrays.asList`
  2. 刪除後**必須接收返回值**:`arr = ArrayUtils.remove(arr, 2)`
  3. 索引越界拋異常,**業務代碼需捕獲或預檢**
  4. 物件陣列刪除後,**原陣列元素引用仍存在**,若涉及敏感資料需手動 `null` 清理
  5. 大陣列頻繁刪除 → **資料結構選型錯誤**,改用 `ArrayList`/`LinkedList`/專用結構

總結

Java 陣列刪除本質是**新建陣列 + 雙段複製**。**生產環境首選 Apache Commons Lang ArrayUtils**,零依賴場景自建工具類核心邏輯同源。理解 `System.arraycopy` 底層機制、基本型別與物件型別差異、資料結構選型原則,才能寫出高效、正確、可維護的代碼。

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