数组
数组的定义
在Java中,可以使用一下格式来定义一个数组:
int[] x = new int[100];
上述语句就相当于在内存中定义了100个int类型的变量,第一个变量的名称为x[0],第二个变量的名称为x[1],依次类推,第一百个为x[99],这些变量的初始值都为0。为了更好的理解数组的这种定义方式,可以将上面的一句代码分成两句来写,具体如下:
int[] x; //声明一个int[]类型的变量
x = new int[100]; //创建一个长度为100的数组
第一行代码int[] x;声明了一个变量x,该变量的类型为int[],即一个int类型的数组。变量x会占用一块内存单元,它没有被分配初始值。内存中的状态如下图1。
图1:
第二行代码 x = new int[100],创建了一个数组,将数组的地址赋值给变量x。这时内存中的状态会发生变化,如下图2。
图2:
在图2中描述了变量x引用数组的情况。初始值都为0,数组中的最小的索引是0,最大的索引是“数组的长度-1”。程序中可以通过“数组名.length”来获取数组的长度,即元素的个数。
案例1:
public class Example1 {
public static void main(String[] args) {
int[] arr; //声明变量
arr = new int[3]; //创建数组对象
System.out.println("arr[0]=" + arr[0]); //访问数组中的第一个元素
System.out.println("arr[1]=" + arr[1]); //访问数组中的第二个元素
System.out.println("arr[2]=" + arr[2]); //访问数组中的第三个元素
System.out.println("数组的长度是:" + arr.length); //打印数组长度
}
}
数组被成功创建后,数组中元素会被自动赋予一个默认值,根据元素类型的不同,默认初始化的值也是不一样的。
数据类型 | 默认初始化值 | 数据类型 | 默认初始化值 |
---|---|---|---|
byte、short、int、long | 0 | boolean | false |
float、double | 0.0 | 引用数据类型 | null |
char | 空字符’\u0000’ |
案例2:
public class Example2 {
public static void main(String[] args) {
int[] arr = new int[4] //定义可以存储4个整数的数组
arr[0] = 1; //为第1个元素赋值1
arr[1] = 2; //为第2个元素赋值2
//下面的代码是打印数组的每个元素的值
System.out.println("arr[0]=" + arr[0]);
System.out.println("arr[1]=" + arr[1]);
System.out.println("arr[2]=" + arr[2]);
System.out.println("arr[3]=" + arr[3]);
}
}
第3行定义了一个数组,此时数组中每个元素的默认初始值都为0。4、5行代码分别给arr[0]、arr[1]赋值为1和2,因此打印结果中四个元素的值依次为1、2、0、0。
在定义数组是只指定数组的长度,由系统自动为元素赋初值的方式称作动态初始化。在初始化数组时还有一种方式叫做静态初始化,就是在定义数组的同时为数组的每个元素赋值。
1、类型[] 数组名=new 类型[]{元素,元素,...};
2、类型[] 数组名={元素,元素,元素,...};
为了简便,建议采用第二种方式。
数组的常见操作
1、数组的遍历
在操作数组时,经常需要一次访问数组中的每个元素,这种操作称作数组的遍历。
案例3:
public class Example3 {
public static void main(String[] args) {
int[] arr={1, 2, 3, 4, 5}; //定义数组
//使用for循环遍历数组的元素
for (int i=0; i<arr.length; i++) {
System.out.println(arr[i]); //通过索引访问元素
}
}
}
定义一个长度为5的数组arr,数组的角标为0~4。由于for循环中定义的变量 i 的值在循环过程中为0~4,因此可以作为索引,依次去访问数组中的元素,并将元素的值打印出来。
2、数组的最值
案例4:
public class Example4 {
public static void main(String[] args) {
int[] arr={4, 1, 6, 3, 9, 8}; //定义一个数组
int max=getMax{arr}; //调用获取元素最大值的方法
System.out.println("max="+max); //打印最大值
}
public static int getMax(int[] arr) {
int max=arr[0];
//定义变量max用于记住最大数,首先假设第一个元素为最大值
//下面通过一个for循环遍历数组中的元素
for (int x=1; x<arr.length; x++) {
if (arr[x]>max) { //比较arr[x]得值是否大于max
max=arr[x]; //条件成立,将arr[x]的值赋给max
}
}
return max; //返回最大值max
}
}
首先假设数组中的第一个元素arr[0]位最大值,然后使用for循环对数组进行遍历,在遍历的过程中只要遇到比max值还大的元素,就将该元素赋值给max。这样for循环执行完时,返回的max即为数组中的最大值。
3、数组的排序
冒泡排序:
1、从第一个元素开始,将相邻的两个元素依次进行比较,直到最后两个元素完成比较。如果前一个元素比后一个元素大,则交换它们的位置。整个过程完成后,数组中最后一个元素自然就是最大值,这样也就完成了第一轮比较。
2、除了最后一个元素,将剩余的元素继续进行两两比较,过程与第一步相似,这样就可以将数组中的第二大的数放在倒数第二个位置。
3、依次类推,持续对越来越少的元素重复上面的步骤,直到没有任何一对元素需要比较为止。
案例5:
public class Example5 {
public static void main(String[] args) {
int[] arr={9, 8, 3, 5, 2};
System.out.print("冒泡排序前:");
printArray(arr); //打印数组元素
bubbleSort(arr); //调用排序方法
System.out.print("冒泡排序后:");
printArray(arr); //打印数组元素
}
//定义打印数组方法
public static void printArray(int[] arr) {
//循环遍历数组的元素
for (int i=0; i<arr.length; i++) {
System.out.print(arr[i] + " "); //打印元素和空格
}
System.out.print("\n");
}
//定义对数组排序的方法
public static void bubbleSort(int[] arr) {
//定义外层循环
for (int i=0; i<arr.length-1; i++) {
//定义内存循环
for (int j=0; j<arr.length-1-i; j++) {
if (arr[j]>arr[j+1]) { //比较相邻的元素
//下面的三行代码用于交换两个元素
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
System.out.print("第"+(i+1)+"轮排序后:");
printArray(arr); //每轮比较结束打印数组元素
}
}
}
案例5中,bubbleSort()方法中通过一个嵌套for循环实现了冒泡排序。其中,外层循环用来控制进行多少轮比较,每一轮比较都可以确定一个元素的位置,由于最后一个元素不需要进行比较,因此外层循环的次数为arr.length-1。内层循环的循环变量用于控制每轮比较的次数,它被作为角标去比较数组的元素,由于变量在循环过程中是自增的,这样就可以实现相邻元素依次进行比较,在每次比较时如果前者小于后者,就交换两个元素的位置。
第一轮比较中,第一个元素“9”为最大值,因此它在每次比较时都会发生位置的交换,被放到最后一个位置。第二轮比较与第一轮过程类似,元素“8”被放到倒数第二个位置。第三轮比较中,第一次比较没有发生位置的交换,在第二次比较时才发生位置交换,元素“5”被放到倒数第三个位置。第四轮比较只针对最后两个元素,他们比较后发生了位置的交换,元素“3”被放到第二个位置。通过四轮比较,很明显,数组中的各元素已经完成了排序。
值得一提的是,第26~28行代码实现了数组中两个元素的交换,需要关注。
多维数组
在程序中可以通过一个数组来保存某个班级学生的考试成绩,试想一下,如果要统计一个学校各个班级学生的考试成绩,又该如何实现呢?这时就需要用到多维数组,多维数组可以简单地理解为在数组中嵌套数组。在程序中比较常见的就是二维数组。
二维数组的定义有很多方式。
第一种:
int[][] arr=new int[3][4];
上面的代码相当于定义了一个 3 * 4 的二维数组,即二维数组的长度为3,每个二维数组中的元素又是一个长度为4的数组。(其实就是数组中原本应该放实参的地方,放入了形参的地址值)
第二种:
int[][] arr=new int[3][];
第二种方式和第一种方式类似,只不过数组中每个元素的长度不确定。
第三种:
int[][] arr={{1,2}, {3, 4, 5, 6}, {7, 8, 9}};
上面的二维数组中定义了三个元素,这三个元素都是数组,分别是{1,2},{3, 4, 5, 6},{7, 8, 9}。
对二维数组中元素的访问也是通过角标的方式,如需访问二维数组中的第一个元素数组的第二个元素,代码如下:
arr[0][1];
案例6:
public class Example6 {
public static void main(String[] args) {
int[][] arr=new int[3][]; //定义一个长度为3的二维数组
arr[0]=new int[]{11, 12}; //为数组的元素赋值
arr[1]=new int[]{21, 22, 23};
arr[2]=new int[]{31, 32, 33, 34};
int sum=0; //定义变量记录总销售额
for (int i=0; i<arr.length; i++) { //遍历数组元素
int groupSum=0; //定义变量记录小组销售总额
for (int j=0; j<arr.length; j++) { //遍历小组内每个人的销售额
groupSum=groupSum+arr[i][j];
}
sum=sum+groupSum; //累加小组销售额
System.out.println("第"+(i+1)+"小组销售额为:"+groupSum+" 万元。");
}
System.out.println("总销售额为:"+sum+" 万元。");
}
}
案例6中,第3行代码定义了一个长度为3的二维数组,并在4~6行代码中为每个元素赋值。案例6中,sum用来记录总销售额,groupSum用来记录小组销售额。当通过嵌套for循环统计销售额时,外层循环对三个销售小组进行遍历,内层循环对每个小组员工的销售额进行遍历,内层循环每循环一次就相当于将一个小组员工的销售总额统计完毕,赋值给groupSum,然后把groupSum得值与sum的值相加赋值给sum。当外层循环结束时,三个销售小组的销售总额groupSum都累加到sum中,统计出了整个公司的销售总额。