Java 实例 – 删除数组元素(一文讲透)

Java 实例 – 删除数组元素:从基础到实战的完整指南

在 Java 编程中,数组是存储一组相同类型数据的基本结构。然而,数组一旦创建,其长度就固定不变。这给初学者带来了困惑:如果我想从数组中移除某个元素,该怎么办? 这正是本文要深入探讨的核心问题。我们今天要解决的,就是 Java 实例 – 删除数组元素 这个常见又关键的编程任务。

很多开发者会直接认为“数组支持删除”,但现实是:Java 数组本身不支持动态增删。删除元素的本质,其实是“创建一个新数组,把不需要的元素跳过去”。这个过程看似简单,但背后涉及内存管理、索引操作、性能权衡等重要概念。理解这一点,是迈向高级 Java 编程的第一步。

本文将通过多个实际案例,带你一步步掌握删除数组元素的各种方法,从最基础的模拟方式,到使用集合类的高效方案,让你真正掌握“删除”背后的逻辑。


为什么数组不能直接删除元素?

在深入代码之前,先理解一个核心概念:数组的长度是固定的。想象一下,你有一个装满水的玻璃杯(数组),一旦你倒掉一半水(删除元素),杯子的大小并不会变。Java 数组也是如此,它在内存中是一段连续的存储区域,长度由创建时决定,无法改变。

这就像一条高速公路,如果你要“移除”某个收费站(元素),你不能把路砍掉一部分,只能绕道走——也就是创建一条新的高速公路,把不要的收费站排除在外。

因此,所谓的“删除数组元素”,本质上是重新构造一个新数组,只保留你想要的元素。理解这个前提,后续所有方法都变得合情合理。


方法一:手动构建新数组(基础实现)

最原始、最直观的方法,就是遍历原数组,把需要保留的元素逐个复制到新数组中。这个方法虽然效率不高,但逻辑清晰,非常适合初学者理解“删除”的本质。

public class ArrayRemoveExample {
    public static void main(String[] args) {
        // 原始数组:包含 5 个整数
        int[] originalArray = {10, 20, 30, 40, 50};
        
        // 要删除的元素值(例如:30)
        int valueToRemove = 30;
        
        // 用于记录新数组的长度
        int newSize = 0;
        
        // 第一步:遍历原数组,统计需要保留的元素个数
        for (int i = 0; i < originalArray.length; i++) {
            if (originalArray[i] != valueToRemove) {
                newSize++; // 只有不等于目标值的才计数
            }
        }
        
        // 第二步:创建新数组,长度为 newSize
        int[] newArray = new int[newSize];
        
        // 第三步:再次遍历,把保留的元素复制过去
        int index = 0; // 新数组的下标指针
        for (int i = 0; i < originalArray.length; i++) {
            if (originalArray[i] != valueToRemove) {
                newArray[index] = originalArray[i]; // 复制元素
                index++; // 指针后移
            }
        }
        
        // 输出结果
        System.out.println("原数组:" + java.util.Arrays.toString(originalArray));
        System.out.println("删除 " + valueToRemove + " 后:" + java.util.Arrays.toString(newArray));
    }
}

输出结果:

原数组:[10, 20, 30, 40, 50]
删除 30 后:[10, 20, 40, 50]

关键点说明

  • 两次遍历是必要的:第一次统计数量,第二次复制数据。
  • 使用 java.util.Arrays.toString() 可以方便地打印数组内容。
  • 这种方式适用于删除单个元素,但不能处理重复元素的批量删除。

方法二:删除指定索引的元素

有时候,我们需要删除的是“第几个”元素,而不是“值为多少”的元素。比如删除第 2 个元素(索引为 1)。

public class RemoveByIndex {
    public static int[] removeElementAtIndex(int[] arr, int index) {
        // 检查索引是否合法
        if (index < 0 || index >= arr.length) {
            throw new IllegalArgumentException("索引超出范围:" + index);
        }
        
        // 创建新数组,长度比原数组少 1
        int[] result = new int[arr.length - 1];
        
        // 复制索引前的部分
        for (int i = 0; i < index; i++) {
            result[i] = arr[i];
        }
        
        // 复制索引后的部分(跳过目标元素)
        for (int i = index + 1; i < arr.length; i++) {
            result[i - 1] = arr[i]; // 下标减 1,因为新数组少了一位
        }
        
        return result;
    }
    
    public static void main(String[] args) {
        int[] numbers = {100, 200, 300, 400};
        
        System.out.println("原数组:" + java.util.Arrays.toString(numbers));
        
        // 删除索引为 1 的元素(即 200)
        int[] result = removeElementAtIndex(numbers, 1);
        
        System.out.println("删除索引 1 的元素后:" + java.util.Arrays.toString(result));
    }
}

输出:

原数组:[100, 200, 300, 400]
删除索引 1 的元素后:[100, 300, 400]

技巧提示

  • i - 1 的使用是关键:因为新数组比原数组少一个元素,所以后面的元素要“前移一位”。
  • 索引检查是安全编程的基础,不能省略。

方法三:使用 ArrayList 实现动态删除(推荐方案)

既然数组不能动态删除,那我们为什么不换个容器?ArrayList 是 Java 提供的动态数组,支持增删改查,非常适合处理这类需求。

import java.util.ArrayList;
import java.util.Arrays;

public class ArrayListRemoveExample {
    public static void main(String[] args) {
        // 初始化一个 ArrayList,添加元素
        ArrayList<Integer> list = new ArrayList<>(Arrays.asList(10, 20, 30, 40, 50));
        
        System.out.println("原始列表:" + list);
        
        // 删除值为 30 的元素
        list.remove(Integer.valueOf(30)); // 注意:使用包装类,避免与索引混淆
        
        System.out.println("删除 30 后:" + list);
        
        // 删除索引为 1 的元素(即 20)
        list.remove(1);
        
        System.out.println("删除索引 1 的元素后:" + list);
    }
}

输出:

原始列表:[10, 20, 30, 40, 50]
删除 30 后:[10, 20, 40, 50]
删除索引 1 的元素后:[10, 40, 50]

为什么推荐 ArrayList?

  • 自动管理容量,无需手动计算新长度。
  • 提供 remove(Object)remove(int index) 两种重载方法,使用方便。
  • 性能在大多数场景下优于手动数组操作。

方法四:删除所有重复元素(去重)

在实际开发中,我们还可能需要“删除所有重复元素”。这可以用 Set 结合 ArrayList 快速实现。

import java.util.*;

public class RemoveDuplicates {
    public static int[] removeDuplicates(int[] arr) {
        // 使用 LinkedHashSet 保持插入顺序,同时去重
        Set<Integer> set = new LinkedHashSet<>();
        
        // 将所有元素加入 Set
        for (int value : arr) {
            set.add(value);
        }
        
        // 转换回数组
        return set.stream().mapToInt(Integer::intValue).toArray();
    }
    
    public static void main(String[] args) {
        int[] arrayWithDuplicates = {1, 2, 2, 3, 3, 3, 4, 5, 5};
        
        System.out.println("原始数组:" + Arrays.toString(arrayWithDuplicates));
        
        int[] result = removeDuplicates(arrayWithDuplicates);
        
        System.out.println("去重后:" + Arrays.toString(result));
    }
}

输出:

原始数组:[1, 2, 2, 3, 3, 3, 4, 5, 5]
去重后:[1, 2, 3, 4, 5]

小贴士

  • LinkedHashSet 既能去重,又能保持元素插入顺序。
  • stream().mapToInt() 是 Java 8 的函数式编程特性,简洁高效。

总结:选择合适的方法

方法 适用场景 性能 可读性
手动构建新数组 理解原理、小数据量
ArrayList 删除 多次增删、动态需求
Set 去重 去除重复元素

在实际项目中,优先使用 ArrayList。只有在对性能有极致要求的场景(如嵌入式系统),才考虑手动数组操作。


实用建议与常见陷阱

  • 不要直接用 arr.remove(30):数组没有 remove 方法,会编译错误。
  • 删除元素前检查索引范围,避免 IndexOutOfBoundsException
  • 使用包装类 Integer.valueOf() 删除对象,避免与索引混淆。
  • 考虑使用 List 而非数组,除非你有明确的性能或内存限制。

Java 实例 – 删除数组元素 这个看似简单的问题,背后蕴含了对数据结构本质的理解。从固定长度的数组,到可变长度的集合,你的编程思维也在不断进化。希望今天的分享,能让你在处理数据时,更加从容自信。