【Java SE】认识数组
文章目录
- 一、为什么需要数组?
- 二、数组的基本概念
- 什么是数组?
- 数组的创建与初始化
- 1. 数组的创建
- 2. 数组的初始化
- 初始化注意事项:
- 三、数组的使用方法
- 1. 访问数组元素
- 2. 遍历数组
- 四、数组是引用类型
- JVM内存简化模型
- 基本类型与引用类型的区别
- 引用变量的特性
- 认识null
- 五、数组的应用场景
- 1. 作为函数参数
- 2. 作为函数返回值
- 六、数组常用操作实战
- 1. 数组转字符串
- 2. 数组拷贝
- 3. 数组查找
- 4. 数组排序
- 5. 数组逆序
- 七、二维数组
- 总结
数组是Java中最基础也最常用的数据结构之一,它为我们提供了一种高效存储和操作相同类型数据的方式。本文将从数组的基本概念出发,详细讲解数组的创建、初始化、使用方法以及相关实战技巧,帮助你全面掌握Java数组的核心知识。
一、为什么需要数组?
想象一个场景:如果我们需要存储5个学生的成绩,使用基本变量可以这样写:
int score1 = 70;
int score2 = 80;
int score3 = 85;
int score4 = 60;
int score5 = 90;
但如果有20个、100个甚至更多学生呢?显然,创建大量单独的变量既繁琐又难以维护。这时候,数组的价值就体现出来了——它可以存储多个相同类型的元素,并且这些元素在内存中占据连续的空间。
二、数组的基本概念
什么是数组?
数组是相同类型元素的集合,在内存中占据连续的存储空间。可以把数组想象成一排连续的"车位":
- 每个"车位"存储一个元素,且所有元素类型相同
- 每个"车位"有唯一编号(下标),从0开始递增
- 可以通过编号快速访问对应的元素
数组的创建与初始化
1. 数组的创建
Java中创建数组的基本语法:T[] 数组名 = new T[N];
int[] array1 = new int[10]; // 能容纳10个int类型元素的数组
double[] array2 = new double[5]; // 能容纳5个double类型元素的数组
String[] array3 = new String[3]; // 能容纳3个字符串元素的数组
其中,T
是元素类型,N
是数组长度。
2. 数组的初始化
数组初始化分为两种方式:动态初始化和静态初始化。
动态初始化:创建数组时指定长度,元素使用默认值
int[] array = new int[10]; // 所有元素初始化为0
静态初始化:创建数组时直接指定元素值
// 完整格式
int[] array1 = new int[]{0,1,2,3,4,5};
// 简化格式(推荐)
int[] array2 = {0,1,2,3,4,5};
初始化注意事项:
- 静态初始化时,编译器会自动计算数组长度
- 静态初始化的简化格式不能拆分声明和赋值
- 基本类型数组的默认值:数值类型为0,
char
为\u0000
,布尔类型为false
- 引用类型数组的默认值为
null
三、数组的使用方法
1. 访问数组元素
数组通过下标访问元素,语法为数组名[下标]
:
int[] array = {10, 20, 30, 40, 50};
System.out.println(array[0]); // 访问第一个元素,输出10
array[0] = 100; // 修改第一个元素的值
注意:数组下标从0开始,范围是[0, 数组长度-1]
,超出范围会抛出ArrayIndexOutOfBoundsException
异常。
2. 遍历数组
遍历数组就是访问数组中的每个元素,常用两种方式:
普通for循环:
int[] array = {10, 20, 30, 40, 50};
for(int i = 0; i < array.length; i++){ // array.length获取数组长度System.out.println(array[i]);
}
增强for循环(for-each):
int[] array = {1, 2, 3};
for (int x : array) { // 直接获取元素值,无需下标System.out.println(x);
}
四、数组是引用类型
理解数组的引用特性是掌握Java数组的关键,这需要先了解JVM的内存分布:
JVM内存简化模型
- 虚拟机栈:存储局部变量和方法调用信息
- 堆:存储通过
new
创建的对象和数组 - 方法区:存储类信息、常量等
基本类型与引用类型的区别
- 基本类型变量:直接存储值,位于栈中
- 引用类型变量:存储对象在堆中的地址,位于栈中,通过地址操作对象
public static void func() {int a = 10; // 基本类型,栈中直接存储值int[] arr = new int[]{1,2,3,4,5}; // 引用类型,栈中存储地址,数组元素在堆中
}
引用变量的特性
多个引用可以指向同一个数组对象:
int[] array1 = new int[3];
array1[0] = 10;
int[] array2 = array1; // array2和array1指向同一个数组
array2[0] = 20; // 修改array2指向的数组,array1也会受影响
System.out.println(array1[0]); // 输出20
认识null
null
表示"空引用",即不指向任何对象:
int[] arr = null;
System.out.println(arr[0]); // 抛出NullPointerException
五、数组的应用场景
1. 作为函数参数
数组作为参数传递时,传递的是引用(地址),函数内部修改会影响原数组:
public static void main(String[] args) {int[] arr = {1, 2, 3};func(arr);System.out.println("arr[0] = " + arr[0]); // 输出10
}public static void func(int[] a) {a[0] = 10; // 修改数组内容
}
2. 作为函数返回值
数组可以作为返回值,方便返回多个结果:
// 获取斐波那契数列的前n项
public static int[] fib(int n) {if(n <= 0) return null;int[] array = new int[n];array[0] = array[1] = 1;for(int i = 2; i < n; i++) {array[i] = array[i-1] + array[i-2];}return array;
}
六、数组常用操作实战
1. 数组转字符串
使用Arrays.toString()
方法可以方便地将数组转为字符串:
import java.util.Arrays;int[] arr = {1,2,3,4,5};
System.out.println(Arrays.toString(arr)); // 输出[1, 2, 3, 4, 5]
2. 数组拷贝
使用Arrays.copyOf()
或Arrays.copyOfRange()
进行数组拷贝:
int[] arr = {1,2,3,4,5};
// 拷贝整个数组
int[] newArr = Arrays.copyOf(arr, arr.length);
// 拷贝指定范围(从下标2到4,不包含4)
int[] rangeArr = Arrays.copyOfRange(arr, 2, 4); // 结果为[3,4]
3. 数组查找
顺序查找:遍历数组寻找目标元素
public static int find(int[] arr, int target) {for (int i = 0; i < arr.length; i++) {if (arr[i] == target) {return i; // 找到返回下标}}return -1; // 没找到返回-1
}
二分查找:针对有序数组的高效查找(时间复杂度O(log n))
public static int binarySearch(int[] arr, int target) {int left = 0;int right = arr.length - 1;while (left <= right) {int mid = (left + right) / 2;if (target < arr[mid]) {right = mid - 1; // 去左侧查找} else if (target > arr[mid]) {left = mid + 1; // 去右侧查找} else {return mid; // 找到返回下标}}return -1; // 没找到
}
4. 数组排序
冒泡排序:通过相邻元素比较交换实现排序
public static void bubbleSort(int[] arr) {for (int i = 0; i < arr.length; i++) {for (int j = 1; j < arr.length - i; j++) {if (arr[j-1] > arr[j]) {// 交换元素int tmp = arr[j-1];arr[j-1] = arr[j];arr[j] = tmp;}}}
}
实际开发中推荐使用Java内置的排序方法:
Arrays.sort(arr); // 效率更高的排序实现
5. 数组逆序
通过首尾交换实现数组逆序:
public static void reverse(int[] arr) {int left = 0;int right = arr.length - 1;while (left < right) {// 交换左右元素int tmp = arr[left];arr[left] = arr[right];arr[right] = tmp;left++;right--;}
}
七、二维数组
二维数组可以理解为"数组的数组",即每个元素都是一个一维数组:
// 定义二维数组
int[][] arr = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12}
};// 遍历二维数组
for (int row = 0; row < arr.length; row++) {for (int col = 0; col < arr[row].length; col++) {System.out.print(arr[row][col] + "\t");}System.out.println();
}
注意:
- 二维数组要用
{}
手动区分行和列 - 定义时行不能省略,列可以省略
- 可以定义不规则数组:
int[][] arr = new int[3][];
arr[1] = new int[3];
arr[2] = new int[5];
总结
数组作为Java中最基础的数据结构,掌握它的使用是进行Java编程的必备技能。本文介绍了数组的概念、创建、初始化、使用方法及常见操作,这些知识将为你后续学习更复杂的数据结构打下坚实基础。
数组的核心特点是连续存储空间和固定长度,这使得它具有快速访问的优势,但也带来了长度不可变的限制。在实际开发中,要根据具体需求选择合适的数据结构,当需要动态调整大小的集合时,可以考虑Java集合框架中的ArrayList
等类。