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