目录
数组
1.数组的基本概念
2.数组的声明与创建
3.数组的使用
for-each循环:
数组在方法中的使用:
Arrays类中的常用方法:
4.多维数组
5.稀疏数组
数组
1.数组的基本概念
-
数组是一种数据结构,是同一类型数据的有序集合。
-
每一个数据称作一个数组元素,每个数组元素可以通过一个整型下标来访问它们。
2.数组的声明与创建
-
首先必须声明数组变量,才能在程序中使用数组。java中有两种方法声明数组变量:
int[] arrays;
int arrays[];
-
两种方法有相同的作用,但java中大多默认采用方式1
-
方式2雷同于C语言的编写习惯,方便C程序员转java
-
数组声明之后,需要初始化才能被正常使用,java中有两种方法可以初始化一个数组
-
动态初始化:即使用new运算符创建一个数组
int[] a;
a = new int[100];
//也可以直接在一条语句中声明和创建
int[] a = new int[100]
数组类型 数组变量名 数组长度
需要注意的几个点:
-
数组下标是从0开始,如例中数组a 的下标为0~99;
-
数组长度不要求是常量,即int[] b=new int[n]会创建一个长度为n的数组
-
使用new运算符创建的数组包含了默认初始化。这是因为数组的元素相当于类的的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。
-数字数组所有元素初始化为0;
-boolean数组所有元素初始化为false;
-对象数组所有元素初始化为null;
-
动态初始化后给数组元素赋值直接使用=即可
b[3]=100;//给第4个元素赋值100
-
静态初始化:如果我们确切知道数组的每个元素的值,可以直接使用{ }进行初始化
int[] c ={1,2,3,6,8,9,100,56,98};
String[] s = {"hello","world","!"}; -
获取数组长度使用array.length命令
-
关于数组需要注意的几个点:
-
数组长度是确定的,一旦被创建就不能再改变它的大小
-
数组中元素必须是相同类型,不能是混合类型
-
数组元素可以是任何类型,包括基本类型和引用类型
-
数组对象本身是在堆中的
-
ArrayIndexOutOfBoundsException:数组下标越界异常
-
java中允许数组长度为0
3.数组的使用
for-each循环:
-
数组是一种数据结构,是同一类型数据的有序集合。
-
每一个数据称作一个数组元素,每个数组元素可以通过一个整型下标来访问它们。
2.数组的声明与创建
-
首先必须声明数组变量,才能在程序中使用数组。java中有两种方法声明数组变量:
int[] arrays;
int arrays[];
-
两种方法有相同的作用,但java中大多默认采用方式1
-
方式2雷同于C语言的编写习惯,方便C程序员转java
-
数组声明之后,需要初始化才能被正常使用,java中有两种方法可以初始化一个数组
-
动态初始化:即使用new运算符创建一个数组
int[] a;
a = new int[100];
//也可以直接在一条语句中声明和创建
int[] a = new int[100]
数组类型 数组变量名 数组长度
需要注意的几个点:
-
数组下标是从0开始,如例中数组a 的下标为0~99;
-
数组长度不要求是常量,即int[] b=new int[n]会创建一个长度为n的数组
-
使用new运算符创建的数组包含了默认初始化。这是因为数组的元素相当于类的的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。
-数字数组所有元素初始化为0;
-boolean数组所有元素初始化为false;
-对象数组所有元素初始化为null;
-
动态初始化后给数组元素赋值直接使用=即可
b[3]=100;//给第4个元素赋值100
-
静态初始化:如果我们确切知道数组的每个元素的值,可以直接使用{ }进行初始化
int[] c ={1,2,3,6,8,9,100,56,98};
String[] s = {"hello","world","!"}; -
获取数组长度使用array.length命令
-
关于数组需要注意的几个点:
-
数组长度是确定的,一旦被创建就不能再改变它的大小
-
数组中元素必须是相同类型,不能是混合类型
-
数组元素可以是任何类型,包括基本类型和引用类型
-
数组对象本身是在堆中的
-
ArrayIndexOutOfBoundsException:数组下标越界异常
-
java中允许数组长度为0
3.数组的使用
for-each循环:
首先必须声明数组变量,才能在程序中使用数组。java中有两种方法声明数组变量:
int[] arrays; int arrays[];
-
两种方法有相同的作用,但java中大多默认采用方式1
-
方式2雷同于C语言的编写习惯,方便C程序员转java
数组声明之后,需要初始化才能被正常使用,java中有两种方法可以初始化一个数组
-
动态初始化:即使用new运算符创建一个数组
int[] a; a = new int[100]; //也可以直接在一条语句中声明和创建 int[] a = new int[100] 数组类型 数组变量名 数组长度
需要注意的几个点:
-
数组下标是从0开始,如例中数组a 的下标为0~99;
-
数组长度不要求是常量,即int[] b=new int[n]会创建一个长度为n的数组
-
使用new运算符创建的数组包含了默认初始化。这是因为数组的元素相当于类的的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。
-数字数组所有元素初始化为0;
-boolean数组所有元素初始化为false;
-对象数组所有元素初始化为null;
-
动态初始化后给数组元素赋值直接使用=即可
b[3]=100;//给第4个元素赋值100
-
-
静态初始化:如果我们确切知道数组的每个元素的值,可以直接使用{ }进行初始化
int[] c ={1,2,3,6,8,9,100,56,98}; String[] s = {"hello","world","!"}; -
获取数组长度使用array.length命令
关于数组需要注意的几个点:
-
数组长度是确定的,一旦被创建就不能再改变它的大小
-
数组中元素必须是相同类型,不能是混合类型
-
数组元素可以是任何类型,包括基本类型和引用类型
-
数组对象本身是在堆中的
-
ArrayIndexOutOfBoundsException:数组下标越界异常
-
java中允许数组长度为0
for-each循环:
java提供一种增强型的循环结构,用以依次处理数组中的每一个元素
int[] a ={1,2,3,4,5};
for (int j : a) {
System.out.println(j);
}
例示代码实现打印数组的全部元素,它实际是以下代码的代替
int[] a ={1,2,3,4,5};
for (int i = 0; i < a.length; i++) {
System.out.println(a[i]);
}
-
优点:代码界面更简洁,不易出现数组下标越界的异常
-
缺点:无法显示下标,无法单独操作数组中的某个元素
数组在方法中的使用:
-
数组可以在构建方法时作为方法的参数,比如我们简单的构建一个打印数组所有元素的方法,此时数组int[] b便是方法的参数,使用时直接在main方法中调用即可:printArray(array);
public static void printArray(int[] b){
for (int i : b) {
System.out.println(i);
}
} -
数组也可以作为方法的返回值,比如构建一个方法实现对数组元素的反转,此时我们使用语句int[] b = reverse(a);即可将数组a中的每个元素的下标反转赋值给数组b
public static int[] reverse(int[] b){
int[] result = new int[b.length];
for (int i = 0, j = result.length-1; i < b.length; i++,j--) {
result[j] = b[i];
}
return result;
Arrays类中的常用方法:
数组可以在构建方法时作为方法的参数,比如我们简单的构建一个打印数组所有元素的方法,此时数组int[] b便是方法的参数,使用时直接在main方法中调用即可:printArray(array);
public static void printArray(int[] b){
for (int i : b) {
System.out.println(i);
}
} 数组也可以作为方法的返回值,比如构建一个方法实现对数组元素的反转,此时我们使用语句int[] b = reverse(a);即可将数组a中的每个元素的下标反转赋值给数组b
public static int[] reverse(int[] b){
int[] result = new int[b.length];
for (int i = 0, j = result.length-1; i < b.length; i++,j--) {
result[j] = b[i];
}
return result; 1.数组拷贝:
-
java中允许将一个数组变量拷贝给另一个数组变量,此时两个变量将引用同一个数组(栈不同,堆相同)
int[] array = {1,2,3};
int[] copyArray = array;
copyArray[0] = 1;//array[0]同样为1
copyArray[1] = 2;//array[0]同样为2
copyArray[2] = 3;//array[0]同样为3
-
如果希望将一个数组的所有值拷贝到一个新的数组中(即两个数组变量分别引用两个地址不同的数组),则需要使用Arrays类中的copyOf方法:
int[] a = {1,3,5,7,9};
int[] b = Arrays.copyOf(a,a.length);
a.length可以替换为任意数字,因此此方法常用以增加数组的大小:
int[] c = Arrays.copyOf(a,2*a.length);
此时数组c长度为a的两倍,多余的元素会被默认初始化。相反,如果长度小于原始数组 的长度,则只拷贝最前面的数据元素。
2.打印数组中的所有值:
利用Arrays类中的toString方法可以打印数组中的所有元素,每一个元素用‘,’分隔,并被放在[ ]中,如对于数组拷贝中的示例
System.out.println(Arrays.toString(a)); System.out.println(Arrays.toString(b)); System.out.println(Arrays.toString(c));
会分别输出
[1, 3, 5, 7, 9] [1, 3, 5, 7, 9] [1, 3, 5, 7, 9, 0, 0, 0, 0, 0]
3.数组排序:
Arrays类中的sort方法可以实现对数值型数组进行排序,如:
int[] a = {1,5,6,9,555,69547,2311,3,44};
Arrays.sort(a);
System.out.println(Arrays.toString(a));
此时会输出 [1, 3, 5, 6, 9, 44, 555, 2311, 69547]
-
补充:冒泡排序法
冒泡排序是最基础的排序方法之一。它包括两层结构:外层冒泡轮数,决定我们比较多少次;内层逐个比较,如果第二个数比前一个数大,则交换位置
public static int[] sort(int[] a){
//定义一个临时变量,作交换使用
int temp = 0;
//外层循环,决定我们比较多少次
for (int i = 0; i < a.length-1; i++) {
//内层循环,比较判断两个数,如果第二个数比第一个数大,则交换位置
//因为每次外层循环之后必定会出来一个最大的数,所以内层判断的轮数要减掉i次无用比较
for (int j = 0; j a[j+1]){
temp = a[j+1];
a[j+1] = a[j];
a[j] = temp;
}
}
}
return a;
4.数组填充:
Arrays类中的fill方法可以实现对数组进行批量赋值
int[] a = new int[10]; Arrays.fill(a,6);//将数组a全部赋值6 Arrays.fill(a,2,4,8);//将数组a[2]~a[4]赋值8
5.数组比较:
Arrays类中的equals方法可以实现对数组进行比较,如果两个数组大小相同,并且下标相同的元素都对应相等,则返回true
int[] a = {1,3,5,7,9};
int[] b = a;
int[] c = Arrays.copyOf(a,a.length+1);
System.out.println(Arrays.equals(a,b));//true
System.out.println(Arrays.equals(a,c));//false
-
其他常用方法见Arrays (Java SE 17 & JDK 17) (oracle.com)
4.多维数组
-
多维数组使用多个下标访问数组元素,即数组的数组。我们以简单的二维数组举例:二维数组可以看作为一个特殊的一维数组,其每一个元素分别为一个一维数组。
-
多维数组的声明与创建遵循一般数组的基本规则,下面我们采用两种初始化方式分别构建两个二维数组
public static void main(String[] args) {
int[][] a1 = new int[3][4];
int[][] a2 ={{1,2,3,5},{4,5,6,7},{7,8,9,10}};
} -
for-each循环不能自动处理二维数组,它是按照行,也就是一维数组处理的。要想访问二维数组的所有元素,需要两个循环的嵌套。
现在我们打印数组a2的所有元素:
for (int[] row:a2) {
System.out.println(Arrays.row);//会打印a2中每个数组元素的地址
System.out.println(Arrays.toString(row));//会打印每个数组元素的数值
for (int i:row) {
System.out.println(i);
}
} 当然我们可以用更简单的Arrays.deepToString方法对多维数组进行打印
System.out.println(Arrays.deepToString(a2));
输出格式为:[[1, 2, 3, 5], [4, 5, 6, 7], [7, 8, 9, 10]]
-
同理,更多维度的数组只要在数组之中进行嵌套即可
5.稀疏数组
-
稀疏数组是一种特殊的多维数组,当一个数组其中的大部分元素为0或者相同元素是,我们可以使用稀疏数组来保存这个数组(压缩)。
-
稀疏数组的处理方式:
-
记录有多少行多少列,有多少个不同值
-
把具有不同值的元素的行、列及元素的值记录在一个小规模的数组中,从而缩小程序的模,如下图,左边是原始数组,右边是稀疏数组
多维数组使用多个下标访问数组元素,即数组的数组。我们以简单的二维数组举例:二维数组可以看作为一个特殊的一维数组,其每一个元素分别为一个一维数组。
多维数组的声明与创建遵循一般数组的基本规则,下面我们采用两种初始化方式分别构建两个二维数组
public static void main(String[] args) {
int[][] a1 = new int[3][4];
int[][] a2 ={{1,2,3,5},{4,5,6,7},{7,8,9,10}};
} for-each循环不能自动处理二维数组,它是按照行,也就是一维数组处理的。要想访问二维数组的所有元素,需要两个循环的嵌套。
现在我们打印数组a2的所有元素:
for (int[] row:a2) {
System.out.println(Arrays.row);//会打印a2中每个数组元素的地址
System.out.println(Arrays.toString(row));//会打印每个数组元素的数值
for (int i:row) {
System.out.println(i);
}
} 当然我们可以用更简单的Arrays.deepToString方法对多维数组进行打印
System.out.println(Arrays.deepToString(a2));
输出格式为:[[1, 2, 3, 5], [4, 5, 6, 7], [7, 8, 9, 10]]
同理,更多维度的数组只要在数组之中进行嵌套即可
-
稀疏数组是一种特殊的多维数组,当一个数组其中的大部分元素为0或者相同元素是,我们可以使用稀疏数组来保存这个数组(压缩)。
-
稀疏数组的处理方式:
-
记录有多少行多少列,有多少个不同值
-
把具有不同值的元素的行、列及元素的值记录在一个小规模的数组中,从而缩小程序的模,如下图,左边是原始数组,右边是稀疏数组
-
- 下面我们实际转化一个稀疏数组
public static void main(String[] args) {
//创建一个原始二维数组
int[][] ori = new int[11][11];
ori[1][2] = 1;
ori[2][3] = 2;
for (int[] row:ori) {
for (int e:row) {
System.out.print(e+" ");
}
System.out.println("t");
}
//转化为稀疏数组
//1.获取有效值的个数
int count = 0;
for (int[] e : ori) {
for (int i : e) {
if (i != 0) {
count++;
}
}
}
System.out.println("有效值的个数:"+count);
//2.创建对应的稀疏数组
int[][] sparseArray = new int[count+1][3];
sparseArray[0][0] = ori.length;
sparseArray[0][1] = ori[ori.length-1].length;
sparseArray[0][2] = count;
//3.遍历二维数组,将非零的值存入稀疏数组中
int a = 0;
for (int i = 0; i



