数组的概述
数组(Array)是Java中的一种引用数据类型,是多个相同类型数据一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。
数组的相关概念
数组名、元素、下标(索引)、数组的长度(元素的个数)。
数组的特点
- 数组是序排列的;
- 数组属于引用数据类型的变量,数组元素既可以是基本数据类型,也可以是引用数据类型;
- 创建数组对象会在内存中开辟一整块连续的空间;
- 数组的长度一旦确定就不能修改了。
数组的分类
按照维度可以分为:一维数组、二维数组、三维数组……
按照元素的类型:基本数据类型元素的数组、引用数据类型元素的数组。
数组的使用
在数组的使用中,我们主要掌握数组的声明和初始化、调用数组指定位置的元素、获取数组的长度、遍历数组、数组元素的默认初始化值、数组的内存解析这五大点。
一维数组的使用
数组的声明和初始化
数组的声明:
//声明格式:数据类型[] 数组名;
//数据类型决定数组里面所储存元素的类型
int[] arr1;
String[] arr2;
数组的初始化:
int[] userId;//先声明
userId = new int[]{11,22};//声明后再初始化
int[] id = new int[]{1001,1002,1003,1004};//数组的静态初始化:数组的初始化和数组元素的赋值操作一起写
String [] names = new String[4];//数组的动态初始化:数组的初始化和数组元素的赋值操作分开写
names[0] = "AA";//数组元素赋值
names[1] = "BB";//数组元素赋值
names[2] = "CC";//数组元素赋值
names[3] = "DD";//数组元素赋值
//数组一旦初始化完成,长度就固定了
//[]中写的就是数组的长度
调用数组指定位置的元素
int[] userId = new int[]{1001,1002,1003,1004,1005};
//调用格式:数组名[下标]
System.out.println(userId[0]);//调用第一个元素(下标为0)
System.out.println(userId[1]);//调用第二个元素(下标为1)
System.out.println(userId[2]);//调用第三个元素(下标为2)
System.out.println(userId[3]);//调用第四个元素(下标为3)
System.out.println(userId[4]);//调用第五个元素(下标为4)
//注意:下标是从0开始的
获取数组的长度
int[] userId = new int[]{1001,1002,1003,1004,1005};
//调用格式:数组名.length()
System.out.println(userId.length);//输出数组的长度 长度为5
//数组元素的个数就是数组的长度
遍历数组
int[] userId = new int[]{1001,1002,1003,1004,1005};
//数组的遍历就要使用到循环,在很多时候,我们循环输出一个东西,我们也称为遍历某个东西
for(int i = 0;i < userId.length;i++){
System.out.println(userId[i]);
}
//i从0开始自增,每自增一次就输出userId数组中下标i对应的元素,直到最后一个元素
数组元素的默认初始化值
- 数组元素是整数:0 包括int short long
- 数组元素是浮点型:0.0 float double
- 数组元素是char型:0或’\u0000′ 不是’0′,是美国标准信息交换代码中的0
- 数组元素是布尔型:false
- 数组元素是引用数据类型时:null
数组的内存解析
栈(stack)+ 堆(heap)+ 方法区(常量池 + 静态域 + ……)
栈:存放局部变量,是线性的
堆:存放new出来的结构(对象、数组)
这里不会使用到方法区,所以不提。
在定义数组时,先是在栈空间中存放数组名,然后再去堆空间中开辟一块连续的内存空间来存放数组里面的数据,然后这个空间会有一个首地址值,然后再将首地址值存放在栈空间中对应的数组名里,如果有赋值的情况,再将默认的值替换为所改的值,所以栈空间中存放的是数组的在堆空间中的地址,并不是直接存放数组。这里有点绕,看图吧:
二维数组的使用
对于二维数组的理解,可以看成一维数组又作为另一个一维数组的元素;其实从数组的底层来看,实际上没有多维数组。看图理解:
数组的声明和初始化
//声明格式:变量类型 数组名[数组外层元素长度][数组内层元素长度];
//数据类型决定数组里面所储存元素的类型
String[][] arr1;//声明二维数组
arr1 = new String[][]{{"AA","BB","CC"},{"DD","EE","FF"},{"GG","HH","II"}};//初始化二维数组
int[][] arr1 = new int[][]{{1,2,3,4},{1,2,3,4},{1,2,3,4}};//二维数组静态初始化
int[][] arr2 = new int[3][4];//二维数组的动态初始化
int[][] arr3 = new int[3][];//二维数组的动态初始化
int[][] arr4 = new int[][4];//这种二维数组的初始化是错误的
调用数组指定位置的元素
在调用二维数组元素的时候我们可以把二维数组看成一个矩阵。如图:
现在就来给说说怎么来看这个矩阵,首先看最左边这块黄色区域,然后再看最上面那快黄色区域,这两块区域就代表下标(又称为索引),比如说我想去找”EE”这个元素,那么先看最左边这块黄色区域,找到”EE”这行所对应的下标(1),然后再看最上面那快黄色区域,找到”EE”这列所对应的下标(1),然后就用”数组名[左边下标][上面下标]”来表示元素所在位置。
String[][] arr1 = new String[][]{{"AA","BB","CC"},{"DD","EE","FF"},{"GG","HH","XX"}};
System.out.println(arr1[0][0]);//AA
System.out.println(arr1[0][1]);//BB
System.out.println(arr1[0][2]);//CC
System.out.println(arr1[1][0]);//DD
System.out.println(arr1[1][1]);//EE
System.out.println(arr1[1][2]);//FF
System.out.println(arr1[2][0]);//GG
System.out.println(arr1[2][1]);//HH
System.out.println(arr1[2][2]);//XX
获取数组的长度
在获取数组长度的时候要区分外层元素和内层元素:
String[][] arr1 = new String[][]{{"AA","BB","CC"},{"DD","EE","FF"},{"GG","HH","XX"},{"YY","ZZ","QQ"}};
System.out.println(arr1.length);//获取外层元素的长度 4
System.out.println(arr1[0].length);//获取内层元素的长度 3
String[][] arr1 = new String[7][9];
System.out.println(arr1.length);//获取外层元素的长度 7
System.out.println(arr1[0].length);//获取内层元素的长度 9
遍历数组
String[][] arr1 = new String[][]{{"AA","BB","CC"},{"DD","EE","FF"},{"GG","HH","XX"},{"YY","ZZ","QQ"}};
for(int i = 0;i < arr1.length;i ++){
for(int j = 0;j < arr1[i].length;j ++){
System.out.print(arr1[i][j] + " ");
}
System.out.println("");
}
数组元素的默认初始化值
针对初始化方法一:int[][] arr = new int[3][4];
- 外层元素初始化值为:地址值
- 内层元素初始化值与一维数组初始化值情况一致
针对初始化方法二:int[][] arr = new int[3][];
- 外层元素初始化值为:null
- 内层元素初始化值为:不可调用,否则报错(NullPointerException 空指针异常)
数组的内存解析
在定义数组时,先是在栈空间中存放数组名,然后再去堆空间中开辟一块连续的内存空间来存放数组里面的数据,然后这个空间会有一个首地址值,然后再将首地址值存放在栈空间中对应的数组名里,然后再依次为内层元素开辟空间,将每个空间的首地址值对应写到外层元素里,如果有赋值的情况,再将默认的值替换为所改的值。
常见数组异常
常见的数组异常分为两种:ArrayIndexOutOfBoundsExcetion(数组下标越界的异常)和NullPointerExcetion(空指针异常)
ArrayIndexOutOfBoundsExcetion
异常原因
在使用数组下标的时候,所使用的数组下标不在正常的取值范围。
String[] name = new String[]{"Tom","Ruddy","Jessye","Jessye"};
System.out.println("我的名字是:" + name[4]);
//在name这个数组中,下标的取值范围是0到3的整数,取4明显超出范围了
解决方法
检查数组使用的下标是否在合法取值范围(0 到 数组长度-1)。
String[] name = new String[]{"Tom","Ruddy","Jessye","Jessye"};
//在上面异常原因时,我们就已经分析了错误的原因,那么现在就需要将下标换成0到3的整数
System.out.println("我的名字是:" + name[0]);
NullPointerExcetion
异常原因
数组为null
String[] arr = new String[5];
arr = null;
System.out.println(arr[0]);
二维数组第二层未定义
int[][] arr1 = new int[9][];
System.out.println(arr1[0][2]);
不能通过null调用方法
String[] arr = new String[]{"cat","dog"};
arr[0] = null;
System.out.println(arr[0].toString());
解决方法
第一个异常原因和第三个异常原因的解决方法就是不要让使用的数组或者数组元素为null;第二个异常原因是二维数组的第二层未定义,那给数组定义一下就行了。
Arrays工具类
Arrays工具类主要操作Array,里面定义了很多操作数组的方法:
equals
boolean equals(int[] a, int[] b) 判断两个数组是否相等
String[] arr1 = new String[]{"cat","dog","fish","pig","pink","sky"};
String[] arr2 = new String[]{"cat","dog","fish","pig","pink"};
String[] arr3 = new String[]{"cat","dog","sky","fish","pig","pink"};
System.out.println(arr1.equals(arr2));//false
System.out.println(arr1.equals(arr3));//false
toString
String toString(int[] a) 输出数组信息
String[] arr1 = new String[]{"cat","dog","fish","pig","pink","sky"};
System.out.println(arr1.toString());//[Ljava.lang.String;@16b98e56
fill
void fill(int[] a, int val) 将指定值填充到数组中
String[] arr1 = new String[]{"cat","dog","fish","pig","pink","sky"};
fill(arr1,"ok");
for (int i = 0;i < arr1.length;i++){
System.out.print(arr1[i] + " ");
}
//输出结果为:ok ok ok ok ok ok
sort
void sort(int[] a) 对数组进行排序
int[] arr1 = new int[]{70,99,44,663,3,55,22,25};
sort(arr1);
for (int i = 0;i < arr1.length;i++){
System.out.print(arr1[i] + " ");
}
//输出结果为:3 22 25 44 55 70 99 663
binarySearch
int binarySearch(int[] a,int key) 对排序后的数组进行二分法检索指定值
int[] arr1 = new int[]{80,99,44,663,3,55,22,25};
sort(arr1);
int index = binarySearch(arr1,55);
System.out.println("3所在位置的索引值是:" + index);//3所在位置的索引值是:4
注意:在使用binarySearch方法之前一定要排序。