Java 数组
Java 数组是一种基本的数据结构,用于存储固定大小的相同类型元素集合。以下是一个简明实用的 Java 数组教程,涵盖定义、创建、操作、常见用法和注意事项,适合初学者快速上手。
1. 数组简介
- 定义:数组是存储一组相同类型数据的连续内存空间,元素通过索引(从 0 开始)访问。
- 特点:
- 固定长度:创建后大小不可变。
- 高效访问:通过索引直接访问,时间复杂度 O(1)。
- 类型安全:只能存储声明的类型(或其子类型)。
- 适用场景:需要存储固定数量的元素,且无需动态调整大小。
2. 声明和创建数组
2.1 声明数组
// 方式1:类型[] 变量名
int[] numbers;
// 方式2:类型 变量名[]
String names[];
- 推荐:使用
类型[]
方式,更清晰。
2.2 创建数组
- 指定大小:
int[] numbers = new int[5]; // 创建长度为5的int数组,元素默认初始化为0
- 初始化值:
int[] numbers = {1, 2, 3, 4, 5}; // 直接初始化
// 或者
int[] numbers = new int[] {1, 2, 3, 4, 5};
- 多维数组:
int[][] matrix = new int[3][4]; // 3行4列的二维数组
int[][] matrix2 = {{1, 2}, {3, 4}, {5, 6}}; // 直接初始化
3. 访问和修改数组
3.1 访问元素
- 使用索引(从 0 开始)访问:
int[] numbers = {10, 20, 30};
System.out.println(numbers[0]); // 输出 10
- 注意:访问越界索引会抛出
ArrayIndexOutOfBoundsException
。
3.2 修改元素
numbers[1] = 50; // 将索引1的元素改为50
System.out.println(numbers[1]); // 输出 50
3.3 数组长度
- 使用
length
属性获取数组大小:
int[] numbers = {1, 2, 3};
System.out.println(numbers.length); // 输出 3
4. 遍历数组
4.1 使用 for 循环
int[] numbers = {1, 2, 3, 4, 5};
for (int i = 0; i < numbers.length; i++) {
System.out.println(numbers[i]);
}
4.2 使用增强型 for 循环(for-each)
int[] numbers = {1, 2, 3, 4, 5};
for (int num : numbers) {
System.out.println(num);
}
- 注意:for-each 适合只读遍历,不能修改索引或数组结构。
4.3 遍历多维数组
int[][] matrix = {{1, 2}, {3, 4}, {5, 6}};
for (int[] row : matrix) {
for (int num : row) {
System.out.print(num + " ");
}
System.out.println();
}
输出:
1 2
3 4
5 6
5. 常用操作
5.1 复制数组
- 使用
Arrays.copyOf
或System.arraycopy
:
import java.util.Arrays;
int[] numbers = {1, 2, 3};
int[] copy = Arrays.copyOf(numbers, numbers.length);
System.out.println(Arrays.toString(copy)); // 输出 [1, 2, 3]
5.2 排序数组
- 使用
Arrays.sort
:
import java.util.Arrays;
int[] numbers = {5, 2, 8, 1};
Arrays.sort(numbers);
System.out.println(Arrays.toString(numbers)); // 输出 [1, 2, 5, 8]
5.3 查找元素
- 使用
Arrays.binarySearch
(要求数组已排序):
import java.util.Arrays;
int[] numbers = {1, 2, 5, 8};
int index = Arrays.binarySearch(numbers, 5);
System.out.println(index); // 输出 2
5.4 填充数组
- 使用
Arrays.fill
:
import java.util.Arrays;
int[] numbers = new int[5];
Arrays.fill(numbers, 10);
System.out.println(Arrays.toString(numbers)); // 输出 [10, 10, 10, 10, 10]
6. 数组与 ArrayList 的对比
- 数组:
- 固定大小,创建后不可变。
- 适合性能要求高、元素数量确定的场景。
- 直接内存操作,效率高。
- ArrayList:
- 动态大小,可自动扩容。
- 提供更多方法(如
add
、remove
)。 - 适合需要频繁增删元素的场景。
转换示例:
import java.util.Arrays;
import java.util.ArrayList;
int[] array = {1, 2, 3};
ArrayList<Integer> list = new ArrayList<>();
for (int num : array) {
list.add(num);
}
System.out.println(list); // 输出 [1, 2, 3]
7. 多维数组
- 定义:数组的数组(如
int[][]
是由多个int[]
组成的数组)。 - 不规则数组:每行长度可以不同。
int[][] jagged = new int[3][];
jagged[0] = new int[] {1, 2};
jagged[1] = new int[] {3, 4, 5};
jagged[2] = new int[] {6};
8. 注意事项
- 越界异常:访问超出
length
的索引会导致ArrayIndexOutOfBoundsException
。 - 默认值:数组创建后自动初始化:
- 数值类型(
int
,double
等):0 或 0.0。 - 布尔类型:
false
。 - 引用类型(如
String
):null
。 - 性能:数组适合高性能场景,但大小固定,需谨慎选择。
- 不可变性:数组长度不可变,需用
Arrays.copyOf
或集合类(如ArrayList
)实现动态调整。
9. 高级示例
9.1 统计数组元素频率
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
int[] numbers = {1, 2, 2, 3, 1, 4};
Map<Integer, Integer> frequency = new HashMap<>();
for (int num : numbers) {
frequency.put(num, frequency.getOrDefault(num, 0) + 1);
}
System.out.println(frequency); // 输出 {1=2, 2=2, 3=1, 4=1}
}
}
9.2 矩阵转置
public class Main {
public static void main(String[] args) {
int[][] matrix = {{1, 2, 3}, {4, 5, 6}};
int rows = matrix.length;
int cols = matrix[0].length;
int[][] transposed = new int[cols][rows];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
transposed[j][i] = matrix[i][j];
}
}
for (int[] row : transposed) {
System.out.println(Arrays.toString(row));
}
}
}
输出:
[1, 4]
[2, 5]
[3, 6]
10. 总结
- 核心概念:数组是固定大小、类型安全的连续存储结构。
- 操作:创建、访问、遍历、排序、复制等,常用
java.util.Arrays
工具类。 - 与集合对比:数组适合固定大小、高性能场景;
ArrayList
适合动态调整。 - 推荐实践:
- 使用
Arrays
类简化操作。 - 检查索引边界,避免越界异常。
- 根据需求选择数组或集合。
如果你需要更深入的某部分(如多维数组操作、性能优化)或具体场景的代码示例,请告诉我!