![](https://i-blog.csdnimg.cn/blog_migrate/ab7f29008ab3dd7175370d2869ab0dca.png)
Java 数组
一、数组概述
- 数组是固定大小的相同类型数据的有序集合。
- 数组本身是引用数据类型,而数组中的元素可以是任何数据类型,包括基本数据类型和引用数据类型。
- 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。
- 数组中的每一个数据被称作一个数组元素,每个数组元素可以通过一个下标(索引)来访问它们。数组索引从
0
开始。 - 数组中存储元素的个数被称为数组长度。数组长度一旦确定,就不能修改。
- 创建数组对象会在内存中开辟一整块连续的空间,而数组名中引用的是这块连续空间的首地址。
- 数组的分类:
- 按照维度:一维数组、二维数组、三维数组、…
- 按照元素的数据类型:基本数据类型元素的数组、引用数据类型元素的数据(即对象数组)
- 数组不仅是
Java
中的一种数据类型,也是最基础的数据结构。 - 数据结构:
- 数据与数据之间的逻辑关系:集合、一对一、一对多、多对多。
- 数据的存储结构:
- 线性表(一对一):顺序表(例:数组)、链表、栈、队列
- 树型结构(一对多):二叉树
- 图型结构(多对多)
- 算法(无边界,具体领域有具体算法):例:排序算法、搜索算法等等。
二、一维数组的声明与初始化
2.1 一维数组的声明
- 必须声明一个数组变量,才能在程序中使用数组。
- 声明数组变量的语法:
dataType[] arrayRefVar;
或dataType arrayRefVar[];
。其中dataType
为数据类型,arrayRefVar
为数组变量名。例:int[] ids;
。- 建议使用
dataType[] arrayRefVar
的格式声明数组变量。dataType arrayRefVar[]
风格是来自C/C++
语言 ,在Java
中采用是为了让C/C++
程序员能够快速理解Java
语言。
- 建议使用
- 声明了数组,只是得到了一个存放数组的变量,并没有为数组元素分配内存空间,不能使用这个数组变量。
- 分配空间就是要告诉计算机在内存中为数组变量分配几个连续的位置来存储数据。
2.2 一维数组的初始化
Java
语言中数组必须先初始化,然后才可以使用。所谓初始化,就是为数组的数组元素分配内存空间,并为每个数组元素赋初始值。 在Java
中可以使用new
关键字来给数组分配空间。- 一维数组的初始化可以分为静态初始化与动态初始化。在初始化数组的同时,可以指定数组大小,也可以分别初始化数组中的每一个元素:
- 静态初始化:初始化时由开发人员显式地指定每个数组元素的初始值,由
JVM
决定数组的长度。静态初始化又可以分为简化格式与完整格式(推荐)- 简化格式:
dataType[] arrayRefVar = {value0,value1,...,valuek};
。其中value0,value1,...,valuek
为数组中存储的数据。例:ids = {1001,1002,1003,1004,1005};
。这种初始化格式也被称为类型推断。 - 完整格式(推荐):
dataType[] arrayRefVar = new dataType[]{value0,value1,...,valuek};
。其中value0,value1,...,valuek
为数组中存储的数据。例:ids = new int[]{1001,1002,1003,1004,1005};
。
- 简化格式:
- 动态初始化:初始化时由开发人员指定数组的长度,由
JVM
初始化每个数组元素的默认值。 数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。格式:arrayRefVar = new dataType[arraySize];
。例:ids = new int[5];
。这个语句做了两件事:- 使用
new dataType[arraySize]
创建了一个数组,在创建时指定数组的大小arraySize
,即数组可以存储数据的最大数量。创建数组之后,元素的值并不确定,需要为每一个数组的元素进行赋值,其下标从0
开始。 - 把新创建的数组的引用赋值给变量
arrayRefVar
。
- 使用
- 静态初始化:初始化时由开发人员显式地指定每个数组元素的初始值,由
- 如果动态初始化只指定了数组长度,那么系统将负责为这些数组元素分配初始值:
- 数组元素的类型是基本类型中的整数类型(
byte
、short
、int
和long
),则数组元素的值是0
。 - 数组元素的类型是基本类型中的浮点类型(
float
、double
),则数组元素的值是0.0
。 - 数组元素的类型是基本类型中的字符类型(
char
),则数组元素的值是'\u0000'
。 - 数组元素的类型是基本类型中的布尔类型(
boolean
),则数组元素的值是false
。 - 数组元素的类型是引用类型(
类
、接口
和数组
),则数组元素的值是null
。
- 数组元素的类型是基本类型中的整数类型(
- 数组的声明和初始化可以用一条语句完成:
dataType[] arrayRefVar = new dataType[arraySize];
- 一旦为数组的每个元素分配了内存空间,每个内存空间里存储的内容就是该数组元素的值,即使这个内存空间存储的内容为空,这个空也是一个值(
null
)。 - 不管以哪种方式来初始化数组,只要为数组元素分配了内存空间,数组元素就具有了初始值。初始值的获得有两种形式,一种由系统自动分配,另一种由开发人员指定。
三、数组使用
\quad
数组元素是通过索引访问的。数组索引从0
开始,所以索引值从0
到arrayRefVar.length-1
,其中arrayRefVar.length
返回arrayRefVar
数组长度。如果索引不在 [0
,arrayRefVar.length-1
] 范围,则报ArrayIndexOutOfBoundsException
数组下标越界异常。
3.1 Java 内存(简要分析)
\quad
数组在Java
内存存储的情形大致如下:
3.1.1 堆(heap)
- 存放
new
的对象和数组。 - 可以被所有的线程共享,不会存放别的对象引用。
3.1.2 栈(stack)
- 栈是一种线性结构。
- 存放基本变量类型(会包含这个基本类型的具体数值)。
- 存放引用对象的变量(会存放这个引用在堆里面的具体地址)。
3.1.3 方法区
- 存放常量池和
static
静态域。 - 可以被所有的线程共享。
3.2 获取数组元素
3.2.1 获取单个元素
- 获取单个元素是指获取数组中的一个元素,例:第一个元素或最后一个元素。
- 获取单个元素的方法非常简单,指定元素所在数组的索引即可。
- 注:
Java
数组索引不可以为负数,这一点要与python
区别。
- 注:
- 语法格式:
arrayName[index];
。其中,arrayName
表示数组变量,index
表示下标,下标为0
表示获取第一个元素,下标为array.length-1
或-1
表示获取最后一个元素。 - 当指定的下标值超出数组的总长度时,会拋出
ArraylndexOutOfBoundsException
异常。
3.2.2 获取全部元素
- 当数组中的元素数量不多时,要获取数组中的全部元素,可以使用下标逐个获取元素。
- 如果数组中的元素过多,可以使用循环语句遍历获取全部元素:
for (int i = 0; i < array.length; i++) { System.out.println(array[i]); }
- 使用增强型
for
循环遍历获取全部元素。
3.3 数组的基本特点
- 数组长度是固定的。数组一旦被初始化,它的大小就是不可以被改变的。
- 数组中的元素必须是相同类型,不允许出现混合类型。
- 数组中的元素可以是任何数据类型,包括基本类型和引用类型。
- 数组变量属于引用类型,可以被看成对象,数组中的每个元素相当于该对象的成员变量。
- 数组本身就是对象,
Java
中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。
3.4 For-Each 循环
JDK 1.5
引进了一种新的循环类型,被称为For-Each
循环或增强型for
循环,它能在不使用下标的情况下遍历数组。(点此了解)- 示例:
foreach
循环遍历数组并打印public class Demo01 { public static void main(String[] args) { // 初始化数组 int[] array = {10,20,30,40,50,60,70,80,90}; // foreach循环 for (int num : array) { System.out.println(num); } } }
3.5 数组作为方法参数
- 数组可以作为参数传递给方法。
- 数组可以作为返回值返回给方法。
- 示例:找出一个数组的最大值与最小值,并以数组形式返回。
public class Demo02 { public static void main(String[] args) { double[] array = new double[100]; // 为数组赋值随机数 for (int i = 0; i < array.length; i++) { array[i] = Math.random() * 100; // 每五个数字换一行 if (i != 0 && i % 5 == 0){ System.out.println(); } System.out.print(array[i]+"\t"); } double[] minMax = minMax(array); System.out.println("\n\t数组的最小值为:"+minMax[0]+",最大值为:"+minMax[1]); } // 找出数组中的最大值与最小值 public static double[] minMax(double[] array) { double min = array[0];// 假设数组第 0 个元素为最小值 double max = array[9];// 假设数组第 9 个元素为最大值 for (double num : array) { if (min > num) {// 找到数组最小值 min = num; } if (max < num) {// 找到数组最大值 max = num; } } return new double[]{min,max}; } }
四、多维数组
- 多维数组可以看成是数组的数组,例:二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。
- 多维数组的每个数组元素的长度可以不一致。
- 多维数组与一维数组相同,都是通过索引对元素进行访问的。例:
array[2][3]
即访问array
数组第2
行第3
列的元素。 - 从数组底层的运行机制来看,其实没有多维数组。
4.1 初始化
- 注:声明多维数组时可将方括号
[]
分开书写,例:int[] array[]
、int[][] array[]
、int[] array[][]
等。
4.1.1 静态初始化
- 声明数组的同时使用大括号直接对数组赋值。
- 以二维数组为例:
int[][] array = new int[][]{{1,2},{3,4},{5,6}}
,此语句声明了一个3
行2
列的二维数组。 - 注:多维数组的每个数组元素的长度可以不一致,例:
int[][] array = {{1},{2,3},{4,5,6}};
4.1.2 动态初始化
1. 直接为每一维分配空间
- 格式:
type[][]...[] arrayName = new type[length1][length2]...[lengthN];
。其中type
可以为基本数据类型和引用数据类型,length1
、length2
、...
、lengthN
必须为正整数。 - 二维数组:
type[][] arrayName = new type[rowLength][columnLength];
。其中rowLength
表示行长度,columnLength
表示列长度。示例:int[][] array = new int[3][3];
。
2. 从最高维开始,分别为每一维分配空间
- 首先为最高维分配引用空间,也就是为最高维能保存数据的最大长度,然后再为其每个数组元素单独分配空间。
- 只有最高维是必须指定长度的。
- 当调用未分配空间的数组元素时,会报错
NullPointerException
空指针异常。 - 示例:
public class Demo04 { public static void main(String[] args) { int[][] numArray = new int[2][];// 创建 2 行二维数组 numArray[0] = new int[3];// 第 0 行有 3 列 numArray[0][0] = 1; numArray[0][1] = 2; numArray[0][2] = 3; numArray[1] = new int[]{4,5,6,7,8}; // 第 1 行直接赋值 5 个元素 for (int[] array : numArray) { for (int num : array) { System.out.print(num + ","); } System.out.println(); } } }
3. 默认初始化值
- 针对初始化方式
1
:例:int[][] array = new int[4][3];
- 外层元素的初始化值:地址值。
- 最内层元素的初始化值:与一维数组初始化情况相同。
- 针对初始化方式
2
:例:int[][] array = new int[4][];
- 分配空间的外层元素的初始化值:
null
。 - 未分配空间内层元素的初始化值:不能调用,会报错
NullPointerException
空指针异常。
- 分配空间的外层元素的初始化值:
4.2 多维数组长度
i n t [ ] 1 [ ] 2 ⋯ [ ] n a r r a y = n e w i n t [ ] 1 [ ] 2 ⋯ [ ] n { ⋯ } ; \quad int []_1[]_2\cdots[]_n\ array = new\ int[]_1[]_2\cdots[]_n\{\cdots\}; int[]1[]2⋯[]n array=new int[]1[]2⋯[]n{⋯};
1-D
长度:array.length
。2-D
长度:array[0].length
。3-D
长度:array[0][0].length
。......
n-D
长度: a r r a y [ 0 ] 1 [ 0 ] 2 ⋯ [ 0 ] n − 1 . l e n g t h array[0]_1[0]_2\cdots[0]_{n-1}.length array[0]1[0]2⋯[0]n−1.length