Java中的数组是一种基础且重要的数据结构,用于存储固定大小的相同类型元素。掌握数组的操作对于编写高效、可维护的代码至关重要。以下从基础到进阶技巧全面解析Java中数组的操作。
一、数组的基础操作
1. 声明与初始化
在Java中,数组可以通过以下方式声明和初始化:
- 声明:指定数组的类型和名称。
int[] numbers; // 声明一个整型数组
- 静态初始化:直接赋值。
int[] numbers = {1, 2, 3, 4, 5}; // 静态初始化
- 动态初始化:指定数组长度并分配内存。
int[] numbers = new int[5]; // 动态初始化,长度为5,默认值为0
2. 访问与修改元素
通过索引访问或修改数组元素(索引从0开始):
int[] numbers = {10, 20, 30, 40, 50};
System.out.println(numbers[0]); // 输出第一个元素:10
numbers[2] = 35; // 修改第三个元素为35
3. 获取数组长度
使用length
属性获取数组长度:
int[] numbers = {1, 2, 3, 4, 5};
System.out.println("数组长度:" + numbers.length); // 输出:5
4. 遍历数组
- 使用普通
for
循环:for (int i = 0; i < numbers.length; i++) { System.out.println(numbers[i]); }
- 使用增强型
for
循环(推荐用于只读操作):for (int num : numbers) { System.out.println(num); }
二、进阶技巧
1. 多维数组
Java支持多维数组,最常见的是二维数组:
- 声明与初始化:
int[][] matrix = new int[3][3]; // 创建一个3x3的二维数组 int[][] matrix = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; // 静态初始化
- 访问与修改:
System.out.println(matrix[0][0]); // 输出第一行第一列元素:1 matrix[1][2] = 10; // 修改第二行第三列元素为10
2. 数组复制
- 浅拷贝:使用
Arrays.copyOf()
方法。int[] original = {1, 2, 3}; int[] copy = Arrays.copyOf(original, original.length);
- 深拷贝:对于对象数组,需手动实现深拷贝以避免引用共享问题。
3. 排序与搜索
- 排序:使用
Arrays.sort()
对数组进行升序排序。int[] numbers = {5, 2, 8, 1, 3}; Arrays.sort(numbers); // 排序后:{1, 2, 3, 5, 8}
- 二分查找:使用
Arrays.binarySearch()
在已排序数组中查找元素。int index = Arrays.binarySearch(numbers, 3); // 返回索引:2
4. 填充数组
使用Arrays.fill()
快速填充数组:
int[] numbers = new int[5];
Arrays.fill(numbers, 10); // 将所有元素填充为10
5. 数组转集合
将数组转换为List
,方便使用集合工具类:
String[] array = {"apple", "banana", "cherry"};
List<String> list = Arrays.asList(array);
注意:Arrays.asList()
返回的List
是固定大小的,无法动态增删元素。
6. 流式操作(Java 8+)
利用Stream
API对数组进行函数式操作:
- 过滤:
int[] numbers = {1, 2, 3, 4, 5}; int[] filtered = Arrays.stream(numbers).filter(n -> n > 3).toArray();
- 映射:
int[] squared = Arrays.stream(numbers).map(n -> n * n).toArray();
- 求和:
int sum = Arrays.stream(numbers).sum();
三、注意事项与最佳实践
-
数组越界检查 访问数组时务必确保索引合法,否则会抛出
ArrayIndexOutOfBoundsException
。int[] numbers = {1, 2, 3}; System.out.println(numbers[3]); // 抛出异常
-
避免硬编码数组长度 使用
length
属性代替硬编码,提高代码灵活性。 -
性能优化
- 对于大数组操作,优先使用
System.arraycopy()
,它比手动循环复制效率更高。 - 在频繁查询的场景下,先对数组排序再使用二分查找。
- 对于大数组操作,优先使用
-
不可变数组 如果需要不可变数组,可以使用
Collections.unmodifiableList()
包装List
。
四、实战示例
示例1:统计数组中每个数字出现的次数
import java.util.HashMap;
import java.util.Map;
public class ArrayExample {
public static void main(String[] args) {
int[] numbers = {1, 2, 2, 3, 3, 3};
Map<Integer, Integer> countMap = new HashMap<>();
for (int num : numbers) {
countMap.put(num, countMap.getOrDefault(num, 0) + 1);
}
System.out.println(countMap); // 输出:{1=1, 2=2, 3=3}
}
}
示例2:矩阵转置
public class MatrixTranspose {
public static void main(String[] args) {
int[][] matrix = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int[][] transposed = new int[3][3];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
transposed[j][i] = matrix[i][j];
}
}
// 打印转置后的矩阵
for (int[] row : transposed) {
System.out.println(Arrays.toString(row));
}
}
}
通过以上内容的学习与实践,相信你已经掌握了Java中数组的基本操作与进阶技巧。无论是日常开发还是算法竞赛,熟练运用数组都将为你提供强大的工具支持!