数组
Java 数组详解:基础结构与核心操作
数组是 Java 中最基础的数据结构之一,用于存储相同数据类型的元素集合。其核心特点是固定长度和随机访问(通过索引快速定位元素),是许多高级集合类(如 ArrayList)的底层存储结构。本文将从数组的初始化、多维数组、特性及应用场景等方面,全面解析 Java 数组的本质。
数组的基本概念
- 定义:数组是相同数据类型元素的有序集合,每个元素通过唯一索引(下标)访问,索引从
0开始。 - 本质:数组在内存中是连续的存储空间,因此支持
O(1)时间复杂度的随机访问。 - 长度固定:数组一旦初始化,长度不可修改(若需动态调整,需手动复制到新数组)。
一维数组的初始化
数组的初始化分为静态初始化和动态初始化,核心区别在于是否在初始化时直接指定元素值。
静态初始化
初始化时直接为每个元素赋值,数组长度由元素个数自动确定。
语法:
// 方式1:简化语法(声明时直接赋值)
数据类型[] 数组名 = {元素1, 元素2, ..., 元素n};
// 方式2:完整语法(可用于声明后赋值)
数据类型[] 数组名;
数组名 = new 数据类型[]{元素1, 元素2, ..., 元素n};
示例:
// 静态初始化整数数组
int[] numbers = {1, 2, 3, 4};
// 静态初始化字符串数组(声明后赋值)
String[] names;
names = new String[]{"Alice", "Bob", "Charlie"};
动态初始化
初始化时仅指定数组长度,系统为元素分配默认值,后续再手动赋值。
语法:
数据类型[] 数组名 = new 数据类型[长度];
系统默认值规则:
- 基本类型:
- 整数类型(
byte、short、int、long)→0 - 浮点类型(
float、double)→0.0 - 布尔类型(
boolean)→false - 字符类型(
char)→'\u0000'(空字符)
- 整数类型(
- 引用类型(如
String、对象)→null
示例:
// 动态初始化整数数组(长度为3,默认值为0)
int[] scores = new int[3];
scores[0] = 90; // 手动为第一个元素赋值
scores[1] = 85;
scores[2] = 95;
// 动态初始化对象数组(默认值为null)
Object[] objects = new Object[2];
objects[0] = new Object(); // 手动赋值
数组的访问与遍历
- 访问元素:通过
数组名[索引]访问,如numbers[0]表示第一个元素。 - 遍历元素:使用
for循环或增强for循环(for-each)。
int[] numbers = {1, 2, 3, 4};
// 普通for循环(可修改元素)
for (int i = 0; i < numbers.length; i++) { // length为数组长度属性
System.out.println("索引" + i + ":" + numbers[i]);
numbers[i] *= 2; // 修改元素值
}
// 增强for循环(仅用于读取,无法修改元素)
for (int num : numbers) {
System.out.println("元素:" + num);
}
多维数组
Java 中的多维数组本质是 “数组的数组”,即数组中的元素仍是数组。最常用的是二维数组,可理解为 “表格”(行 + 列),但支持 “非矩形” 结构。
二维数组的静态初始化
直接指定每个 “子数组” 的元素,子数组长度可不同(非矩形数组)。
语法:
// 方式1:简化语法
数据类型[][] 数组名 = {{元素1, 元素2}, {元素3}, ...};
// 方式2:完整语法
数据类型[][] 数组名 = new 数据类型[][]{{元素1, 元素2}, {元素3}, ...};
示例:
// 矩形数组(每行长度相同)
int[][] matrix1 = {{1, 2}, {3, 4}, {5, 6}};
// 非矩形数组(每行长度不同)
int[][] matrix2 = {{1}, {2, 3}, {4, 5, 6}};
二维数组的动态初始化
分两种情况:指定行数和列数(矩形数组),或仅指定行数(后续手动定义每行长度,非矩形数组)。
语法:
// 1. 矩形数组(指定行数和列数)
数据类型[][] 数组名 = new 数据类型[行数][列数];
// 2. 非矩形数组(先指定行数,再定义每行长度)
数据类型[][] 数组名 = new 数据类型[行数][];
数组名[0] = new 数据类型[列数1];
数组名[1] = new 数据类型[列数2];
...
示例:
// 1. 动态初始化矩形数组(3行2列)
int[][] rectMatrix = new int[3][2];
rectMatrix[0][0] = 1;
rectMatrix[0][1] = 2;
// ... 其余元素默认值为0
// 2. 动态初始化非矩形数组(3行,每行长度分别为1、2、3)
int[][] irregularMatrix = new int[3][];
irregularMatrix[0] = new int[1]; // 第1行长度1
irregularMatrix[1] = new int[2]; // 第2行长度2
irregularMatrix[2] = new int[3]; // 第3行长度3
二维数组的遍历
需使用嵌套循环,外层循环遍历 “行”,内层循环遍历 “列”。
int[][] matrix = {{1, 2}, {3, 4, 5}, {6}};
// 遍历所有元素
for (int i = 0; i < matrix.length; i++) { // matrix.length 为行数
int[] row = matrix[i]; // 获取第i行的子数组
for (int j = 0; j < row.length; j++) { // row.length 为当前行的列数
System.out.print(matrix[i][j] + " ");
}
System.out.println(); // 换行
}
输出:
1 2
3 4 5
6
数组的核心特性
长度固定:初始化后
length属性不可修改,若需动态扩容,需通过Arrays.copyOf复制到新数组。int[] numbers = {1, 2, 3}; // 扩容为原长度的2倍 numbers = Arrays.copyOf(numbers, numbers.length * 2); // 结果:[1, 2, 3, 0]类型一致性:数组中的元素必须是相同类型(或其子类型,如
Object[]可存储任何对象)。随机访问高效:通过索引访问元素的时间复杂度为
O(1),优于链表(O(n))。引用传递:数组是引用类型,赋值操作传递的是内存地址(修改一个变量会影响其他引用)。
int[] a = {1, 2}; int[] b = a; b[0] = 100; System.out.println(a[0]); // 输出100(a和b指向同一数组)支持克隆:通过
clone()方法创建数组的浅拷贝(基本类型复制值,引用类型复制地址)。int[] a = {1, 2}; int[] b = a.clone(); b[0] = 100; System.out.println(a[0]); // 输出1(a和b是不同数组)
数组的应用场景
- 底层存储:
ArrayList、HashMap等集合类底层使用数组存储数据,利用其随机访问优势。 - 批量数据处理:如统计分数、存储批量配置等。
- 算法实现:排序(如快速排序、冒泡排序)、查找(如二分查找)等算法多基于数组实现。
- 矩阵运算:二维数组可表示矩阵,用于数学计算、图像处理等领域