数组总结
所有Java学习总结文章均是根据B站尚硅谷视频总结而来,视频链接如下:https://www.bilibili.com/video/BV1Kb411W75N.
一、数组的概述
1、数组的相关定义
(1)数组:是多个相同类型的数据按一定顺序排列的集合。
(2)数组名:对这些数组所命的名字。
(3)元素:这些相同类型的每一个数据就是元素。
(4)下标(索引):用来找到所需的元素,索引从0开始。
(5)数组长度:存的元素的个数。
2、数组的特点
(1)数组是引用数据类型,数组的元素既可以是基本数据类型,也可以是引用数据类型。
(2)创建数组会在内存中开辟一段连续的空间,数组一旦初始化完成,长度就确定不可修改。
3、数组的分类
(1)按照维度分为一维数组、二维数组。
(2)按照元素的类型分为:引用数据类型元素的数组、基本数据类型元素的数组。
二、一维数组的使用
1、一维数组的声明和初始化
(1)声明:int[ ] arr1;或int arry1[ ];一般用第一种。
(2)初始化:
静态初始化格式:
int[ ] arry = new int[ ]{100,200,300,400};
int[ ] arry = {100,200,300,400};//也可以运行,但不建议
动态初始化格式:
String[ ] names = new String[4];
2、如何调用数组指定位置的元素
(1)、通过角标(索引)的方式调用。角标的值从0开始到数组长度减一结束。例如下边代码:
//数组声明和初始化
String[ ] names = new String[4];
//调用指定位置元素
names[0] = "小张";
names[1] = "小王";
names[2] = "小李";
names[3] = "小赵";
3、如何获取数组的长度
(1)、数组名.length,可以获得数组长度。例如:names.length;
4、如何遍历数组元素
(1)、可以采用for循环遍历数组,具体如下代码。
for(int i;i <names.length;i++){
Sysem.out.println(names[i]);
}
5、数组元素的默认初始化值
(1)、数组元素为整型:0;
(2)、数组元素为浮点型:0.0;
(3)、数组元素为boolean型:false;
(4)、数组元素为char型:0(指的是编码为0的,不等价于’0’);
(5)、数组元素为引用数据类型:null。
6、数组内存分配
(1)、内存的简化结构如下图:
(2)、分析如下一维数组的内存解析
int[] arr = new int[]{1,2,3};
String[] arry = new String[4];
arry[1] = "小王";
arry[2] = "小李";
arry = new String[3];
具体实现过程如下图:
需要注意:此处小王、小李本应该存在于字符串常量池,具体细节后边面向对象再思考。
三、二维数组的使用
二维数组可以看作是两个一维数组的嵌套,即把一个一维数组又作
为另一个一维数组的元素而存在,类似于矩阵的行列式,一般把二维数组看作是一个有几行几列一维数组构成的。
1、二维数组的声明和初始化
(1)声明:int[ ] [ ] arr2;
(2)初始化:
静态初始化:
int[ ] [ ] arry3 = new int[ ] [ ]{{1,2,3},{1,2},{4,7,9}};
动态初始化:
①String[ ] [ ] arry4 = new String[3] [2];//可以认为是定义了一个3行2列二维数组。
②String[ ] [ ] arr5 = new int [3] [ ];//这种方法也可以定义一个二维数组,此时表示定义一个三行列数不确定的数组,即每行列数可变。
2、如何调用数组指定位置的元素
int[ ] [ ] arry3 = new int[ ] [ ]{{1,2,3},{1,5},{4,7,9}};
//调用arry3中的元素2
System.out.println(arry3[0][1]);
String[ ] [ ] arry4 = new String[3] [2];
//调用arry4中的元素第一行第二列的元素
System.out.println(arry4[0][1]);//结果为:null
String[ ] [ ] arr5 = new String [3] [ ];
//这种数组在调用前需要先给它确定列长度
arr5[0] = new String[3];//给第一行确定列长度
//调用arry5中的元素第一行第二列的元素
System.out.println(arry5[0][1]);//结果为:null
3、如何获取数组的长度
(1)、数组名.length,可以获得数组长度,此时获取的为行长度。例如:
String[ ] [ ] arry4 = new String[3] [2];
System.out.println(arry4.length); //结果为3
(2)、数组名[行标].length,可以获得某一行有几列,此时获取的为列长度。例如:
int[ ] [ ] arry3 = new int[ ] [ ]{{1,2,3},{1,5},{4,7,9}};
System.out.println(arry3[0].length); //结果为3
System.out.println(arry3[1].length); //结果为2
4、如何遍历数组元素
(1)、使用嵌套for循环即可实现
String[ ] [ ] arry4 = new String[3] [2];
//利用嵌套for循环即可遍历数组
for(int i = 0; i < arry4.length;i++){
for(int j = 0; j < arry4[i].length;j++)
System.out.println(arry4[i][j]);
}
System.out.println();
运行结果如下图:
5、数组元素的默认初始化值
二维数组分为内层数组元素和外层数组元素。如下数组:
String[ ] [ ] arry = new int [3][2];
外层数组元素为:arry[0]、arry[1]、arry[2];
内层数组元素为:arry [0] [0]、arry [0] [1]、arry [1] [0]、arry [1] [1]、 arry [2] [0]、 arry[2] [1]。
(1)、初始化方式一:String[ ] [ ] arry1 = new int [3][4];
外层变量初始化值为:内层变量(即一维数组)的地址值。
内层变量初始化值为:与一维数组初始化情况一样。
String[][] arry = new String[3][2];
System.out.println(arry[0]); //[Ljava.lang.String;@182decdb(此语句表示一维数组类型为字符串,@后边为所在内存地址)
System.out.println(arry[0][0]); //null
int[][] arryq = new int[3][2];
System.out.println(arryq[0]); //[I@7637f22,内存地址
System.out.println(arryq[0][0]); //0
System.out.println(arryq);//[[I@762efe5d
[Ljava.lang.String;@182decdb(此语句表示一维数组类型为字符串,@后边为所在内存地址)
[[I@762efe5d(此语句表示二维数组类型为int,@后边为所在内存地址)
(2)、初始化方式二:int[ ] [ ] arry = new int[3] [4];
外层变量初始化值为:null。
内层变量初始化值为:未分配不能,不能调用
int[][] arryq = new int[3][];
System.out.println(arryq[0]);//null,具体原因见下文内存分配
System.out.println(arryq[0][0]); //未分配运行出错
System.out.println(arryq);//[[I@4926097b
6、数组内存分配
(1)分析如下二维数组的内存解析:
int[ ][ ] arryq = new int[4][ ];
arryq[1] = new int[ ]{1,2,3,4};
arryq[2] = new int[3];
arryq[2][2] = 20;
System.out.println(arryq[0]); //null
System.out.println(arryq); //[[I@492b
System.out.println(arryq[1]); //[I@76f2
System.out.println(arryq[2]); //[I@344a
实现过程如下图:
三、数组中常见的算法
1、数组元素的赋值
(1)、杨辉三角
输出一个十行的杨辉三角。
1、第一行有一个元素,第n行有n个元素。
2、每一行的第一个元素和最后一个元素都是1.
3、从第三行开始,除第一个元素和最后一个元素外的元素都等于其上边元素和上边前一个元素的和。 即arry[2][1] = arry[1][0]+arry[1][1]。具体格式如下:
1
1 1
1 2 1
1 4 6 4 1
实现代码如下(仅供参考):
public class ArryayYangHuiSanJiao {
public static void main(String[] args) {
// 1、声明并初始化一个二维数组
int[][] arry = new int[10][];
// 2、给二位数组赋值
for (int i = 0; i < arry.length; i++) {
arry[i] = new int[i + 1];
// 给每一行首末元素赋值
arry[i][0] = arry[i][i] = 1;
// 给每行的非首末元素赋值
// if(i > 1) {
for (int j = 1; j < arry[i].length - 1; j++) {
arry[i][j] = arry[i - 1][j] + arry[i - 1][j - 1];
} // }
}
// 3、遍历数组,输出杨辉三角
for (int i = 0; i < arry.length; i++) {
for (int j = 0; j < arry[i].length; j++) {
System.out.print(arry[i][j] + " ");
}
System.out.println();
}
}
}
2、求数值型数组元素的最大值、最小值、平均数、总和等。
定义一个int型一维数组,包含十个元素,分别赋予一些不相等的随机数, 然后求出最大值、最小值、和值、平均值,要求随机数均为两位数。
代码如下(可有不同,仅供参考):
public class ArrayMath {
public static void main(String[] args) {
// 1、定义一个一维数组.
int[] array = new int[10];
// 2、给一维数组赋予随机值
for (int i = 0; i < array.length; i++) {
array[i] = (int) (Math.random() * 90) + 10;
// 3、判断输入的数是否有相同的
for (int j = 0; j < i; j++) {
if (array[i] == array[j]) {
i--;
break;
}
}
}
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
// 4、求最大值、最小值、和值、平均值
int max = array[0], min = array[0];
int sum = 0;
double average = 0;
for (int x = 1; x < array.length; x++) {
if (max < array[x]) {
max = array[x];
}
if (min > array[x]) {
min = array[x];
}
sum += array[x];
}
average = (sum + 0.0) / array.length;
System.out.println("最大值为:" + max + "\n" + "最小值为:" + min + "\n" + "和值为:" + sum + "\n" + "平均值为:" + average);
}
}
3、数组的复制、反转、查找(线性查找、二分法查找)
(1)数组的复制
需要注意数组的复制与赋值的区别:
①复制的数组和原始的数组不在同一个内存空间,改变复制数组的值,不会改变原始数组的值;
②赋值数组与原始数组在同一个内存空间,改变值时原始数组的值也会改变。
实现数组复制代码如下:
String[] array = new String[] { "one", "two", "three", "four", "five" };
//数组的赋值
array1 = array;
//数组的复制
String[] array2 = new String[array.length];
for(int i = 0; i < array.length; i++){
array2[i] = array[i];
}
(2)数组的反转
方式一:直接对原始数组反转,for循环利用一个变量。
String[] array = new String[] { "one", "two", "three", "four", "five" ,"aa","aaa"};
for (int i = 0; i < array.length / 2; i++) {
String temp = array[i];
array[i] = array[array.length - i - 1];
array[array.length - i - 1] = temp;
}
方法二:for循环利用两个变量。
String[] array = new String[] { "one", "two", "three", "four", "five" ,"aa","aaa"};
for (int i = 0,j = array.length-1; i < j; i++,j--) {
String temp = array[i] ;
array[i] = array[j];
array[j] = temp;
}
方法三:新建一个数字,然后反转再赋值给原始数组,此方法效率低。
String[] array = new String[] { "one", "two", "three", "four", "five" ,"aa","aaa"};
String[] array1 = new String[array.length];
for (int i = 0; i <= array1.length / 2; i++) {
String temp = array[i];
array1[i] = array[array1.length - i - 1];
array1[array1.length - i - 1] = temp;
}
array = array1;
(3)数组的查找
①线性查找
String test = "two";
boolean isFlag = true;
for(int i = 0; i <array.length;i++) {
if(test.equals(array[i])) { //比较内容是否相等
System.out.println("找到了所需内容,位置为:"+i);
isFlag = false;
}
}
if(isFlag) {
System.out.println("很遗憾没找到所需要的内容!!!");
}
②二分法查找
在数据量较大时查询速度明显高于线性查找,二分法查找查询必须是有顺序的数。
int[] array2 = new int[] { -34, -20, -10, -5, 1, 4, 5, 8, 9, 20, 30, 40 };
int num = -2;
int headIndex = 0; //初始索引
int endIndex = array2.length - 1; //结束索引
boolean isFlag = true;
while (headIndex <= endIndex) {
int middleIndex = (headIndex + endIndex) / 2;
if (num == array2[middleIndex]) {
System.out.println("找到了所需内容,位置为:" + middleIndex);
isFlag = false;
break;
} else if (num < array2[middleIndex]) {
endIndex = middleIndex - 1;
} else {
headIndex = middleIndex + 1;
}
}
if(isFlag) {
System.out.println("很遗憾没找到所需要的内容!!!");
}
4、数组元素的排序算法
(1)十大排序算法:
选择排序:直接选择排序、堆排序。
交换排序:冒泡排序、快速排序(速度快)。
插入排序:直接插入排序、折半插入排序、shell(希尔)排序。
归并排序,桶式排序,基数排序。
①冒泡排序:
冒泡排序法: 它重复地遍历要排序的元素,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。重复地进行直到没有相邻元素需要交换,也就是说该元素已经排序完成。
执行过程:n个元素需要进行n-1趟,第一趟针对第一个到最后一个元素进行,将最大的一个元素放到最后第二趟,针对第一个元素到倒数第二个元素进行,同样将最大的放到最后…,第n-1趟比较第一个 和第二个元素,将大的放后边即可完成排序。
举例代码如下:
public class BubbleSort {
public static void main(String[] args) {
int[] array = new int[] {200,330,56,77,8,34,-59,-40,-90,100,567}; //长度为11的数组
//几大轮排序
for(int i = 0; i < array.length-1; i++) {
//每轮排序比较的次数
for(int j = 0;j < array.length-i-1; j++) {
//每两个相邻元素之间比较
if(array[j] > array[j+1]) {
int temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
//遍历输出数组
for(int i = 0; i < array.length;i++) {
System.out.print(array[i]+"\t");
}
}
}
四、Arrays工具类常用方法
使用Arrays工具类前首先要导入包:import java.util.Arrays;
1、比较两数组是否相等:boolean equals(int[] a,int[] b);
int[] arr1 = new int[]{1,3,5,7};
int[] arr2 = new int[]{1,3,5,7};
//比较同一索引对应元素是否相等
boolean isFlag = Array.equals(arr1,arr2);
System.out.println(isFlag); //true
2、遍历数组元素:String toString(int[] a);
int[] arr3 = new int[]{1,9,4,0,-4,7};
System.out.println(Arrays.toString(arr3));//[1, 9, 4, 0, -4, 7]
3、替换数组中的元素:void fill(int [ ] a,int val);
int[] arr3 = new int[]{1,9,4,0,-4,7};
Arrays.fill(arr3,9);
System.out.println(Arrays.toString(arr3));//[9, 9, 9, 9, 9, 9]
4、数组元素的排序:void sort(int[] arr);
int[] arr4 = new int[]{1,9,4,0,-4,7};
Arrays.sort(arr4);
System.out.println(Arrays.toString(arr4));[-4, 0, 1, 4, 7, 9]
特别注意:
替换数组中的元素【void fill(int [ ] a,int val);】和数组元素的排序【void sort(int[] arr);】这两个方法,不可以直接用: System.out.println(Arrays.fill(arr3,9));
System.out.println(Arrays.sort(arr4));
这种格式输出,因为这两个方法返回值为void,输出流【System.out.println();】不支持输出void。
5、二分法查找:int binarySearch(int[] a,int key);
需要注意此方法若查询不到所需元素默认返回一个负数,需要在编程时自己处理,防止出错。
int[] arr5 = new int[]{1,9,4,0,-4,7};
int index = Arrays.binarySearch(arr5,-7);
if(index >=0) {
System.out.println(index);
}else {
System.out.println("未找到"); //未找到
}
6、其余方法可查看开发文档链接如下:
https://docs.oracle.com/en/java/javase/16/docs/api/index.html
五、数组中常见的异常
注意:出现异常程序会终止,不会继续向下执行
1、数组角标越界异常:java.lang.ArrayIndexOutOfBoundsException(在索引值没有小于数组的长度或索引为负数时,运行出现)
// 1、数组角标越界异常:java.lang.ArrayIndexOutOfBoundsException
int[] arr = new int[] {1,2,3,4,5};
for(int i = 0;i <= arr.length;i++) {
System.out.println(arr[i]);
}
2、数组空指针异常:java.lang.NullPointerException
//2、数组空指针异常:java.lang.NullPointerException
//情况一:
int[] arr1 = new int[] {1,2,3,4};
arr1 = null;
System.out.println(arr1[0]);
//情况二:
int[][] arr2 = new int[5][];
System.out.println(arr2[0][0]);