第3 章 数 组 数组是由类型相同的元素顺序组成的一个集合,每个数组都有一个唯一的名称,即数组 名。通过数组名和下标可以方便地访问数组中的每个成员。本章主要讲述Java中一维和二 维数组的创建和使用方法。通过本章的学习,应该重点掌握以下主要内容: (1)一维数组的定义和产生方法。 (2)一维数组的初始化方法。 (3)一维数组的引用方法。 (4)二维数组的创建和引用方法。 3.1 数组使用初探 Java程序中通常使用变量来存放各种类型的数据,如将10个数分别存放在10个变量中, 但这会非常麻烦,因为需要的变量名实在太多了。这时就可以考虑用一个数组变量来存放它 们,并通过一个下标来访问存入数组中的每个成员。 【例3.1】 求10个学生某门课程的平均成绩。 分析:如果用变量s1,s2,…,s10来保存10个学生的成绩,显然不合适(变量太多且随 学生人数递增),而如果使用数组s来保存这些成绩,则问题可以处理如下: package code0301; public class AvgGrade { public static void main(String args[]) { int total = 0; int s[] = { 75, 69, 80, 85, 93, 97, 79, 77, 68, 90 }; //定义数组变量s 并赋值 double avg = 0; for (int i = 0; i < 10; i++) { total = total + s[i]; //访问数组成员s[i] } avg = total / 10.0; //求平均分avg System.out.println("The average score is :" + avg); } } 程序运行结果: 数组 第3章 4 1 The average score is :81.3 该问题的求解涉及两个关键点: (1)定义数组变量s,将所有值{75,69,80,85,93,97,79,77,68,90}存入其中。 (2)通过数组变量s加下标i的形式访问数组中每个成员:total=total+s[i]。 3.2 一维数组 与简单变量一样,数组必须先定义后使用。定义数组时,除了要给定数组的名称、数组成 员类型,还要为其分配内存空间并进行初始化。 3.2.1 定义数组 一维数组的定义格式如下: 数据类型数组名[ ]; 其中,数据类型是指数组成员的类型,可以为基本数据类型,也可以为引用数据类型。[] 为数组标记。在定义数组时,不允许在[]内指定数组元素的个数。例如: int a[ ], boolean temp[ ], String s[ ]; 表示数组a的数据类型为int,temp的数据类型为boolean,s的数据类型为类String。 提示:定义数组时,另外一种可选形式为直接将方括号放在变量类型的后边。例如: int[ ] a, boolean[ ] temp, String[ ] s 3.2.2 生成数组 数组定义只是建立了一种数组的引用,还必须使用关键字new 为其分配内存空间,否则 它是无法被访问的。基本形式如下: 数组变量名= new 数据类型[数组长度] 例如: char s[]; s=new char[5]; 的作用是为数组s分配5×2B大小的空间。也可以在定义数组的同时为之分配内存空间, 例如: int temp[]=new int[10]; 3.2.3 初始化数组 当使用关键字new生成数组时,数组中的每个成员都会被自动初始化,初始值依据数组 的类型而定。例如: 数值型的初始值:0; 字符型的初始值:'\0'; 布尔型的初始值:false; 类对象的初始值:null; Java 程序设计(第3 版) 4 2 也可以通过主动赋值的方式对数组进行初始化。例如 int s[ ]=new int[3]; s[0]=1; s[1]=2; s[2]=3 还可以将数组的定义、内存空间分配、初始化工作放在一条语句中,格式如下: 数据类型数组名[ ]={值1,…,值n} 这种数组初始化形式的特点是无须给出数组的长度,系统会根据初始值的数量自动确定 数组的长度,并依次将每个数组成员放在数组中。例如: int s[ ]={1,2,3}; 使得数组长度为3,且s[0]=1;s[1]=2;s[2]=3。 数组不能整体赋值,例如,下列语句是错误的: char s[]=new char[5]; s[]={'a','b','c','d','e'}; //错误 提示:必须给出数组长度,而且数组一旦创建,就不允许再增加它的空间。 3.2.4 访问数组 数组成员的访问是通过数组名和下标来实现的,Java中的下标是从0开始的,依次递增 1,如果数组temp的长度为10,则数组下标为0~9。这些成员分别表示为 temp[0],temp[1],…,temp[9] 对数组中任意成员的引用形式为:数组名[下标]。 例如,temp[4]表示引用数组temp的第5个元素。数组元素的用法和平常使用的普通变 量没有什么差异,也可以被赋值或参与其类型允许的各种运算等。例如: int i=temp[0]%2; temp[1]=temp[0]*5; System.out.println("value="+temp[2]); 使用数组时要注意数组是否越界,每个数组一个属性length,可以通过数组名.length来 获取数组的长度,即数组元素的个数。 3.2.5 实用案例3.1:求一维数组的最大值及位置 为给一维数组进行随机赋值,本例采用Math.random()方法产生随机数。 【例3.2】 求一维数组的最大值及位置。 package Code0302; public class MaxNum { public static void main(String[] args) { final int ARRAY_SIZE = 10; int a[] = new int[ARRAY_SIZE]; int max = 0; int index = 0; //存储最大元素的位置 for (int i = 0; i < a.length; i++) { //本例中a.length=10 a[i] = (int) (Math.random() * 10); //产生随机数,并对数组成员赋值 System.out.print(" " + a[i]); } 数组 第3章 4 3 System.out.println(); max = a[0]; for (int j = 1; j < ARRAY_SIZE; j++) { if (a[j] > max) //判断当前位置的数是否大于最大值max { max = a[j]; index = j; //替换当前的最大值,记住对应位置 } } System.out.println("A[" + index + "] has maximum value " + a[index]); } } 程序可能的输出结果: 2 0 0 1 9 5 1 4 2 7 A[4] has maximum value 9 分析:第一个for循环依次将随机数读入下标为i的数组中,完成初始化操作;第二个 for循环依次取出每个数组元素a[j]的值,并判断其是否为当前最大值。 提示:如果例3.2中第二个for循环改为for(intj=1;j<=ARRAY_SIZE;j++),则 出现数组下标越界的情况,因为a[10]并不存在。 3.3 二维数组 到目前为止使用的都是一维数组,但有时应用中需要使用多维数组才能充分地存储数据。 例如,(x,y)坐标系统中,如果需要存储坐标x和坐标y来标识一个点,则需要使用二维数组, 其中一维用于存储坐标x,另一维用于存储坐标y。 将数组的下标数称为数组的维数,维数大于1的数组称为多维数组。因为多维数组的操 作比较相似,本节重点介绍二维数组。 3.3.1 定义二维数组 二维数组的定义与一维数组相似: 数据类型 数组名[ ][ ]; 两个方括号表示这是一个二维数组。当然,它也支持另一种形式: 数据类型[ ][ ] 数组名; 与一维数组相似,二维数组的创建可以先定义数组,再分配内存空间,也可以同时进行这 两项工作。例如: int temp[][]; temp=new int[2][3]; int temp[][]=new int[2][3]; 这样即创建了一张二维结构的数组,其中行数为2,列数为3。也可将其看作一个长度为 2的一维数组,每个数组成员又是一个长度为3的一维数组。这些数组成员按行排列为 Java 程序设计(第3 版) 4 4 temp[0][0], temp[0][1], temp[0][2] temp[1][0], temp[1][1], temp[1][2] 同样,可以在定义数组的同时对其进行初始化。例如: int temp[][]={{1,2},{3,4},{5,6}} 系统自动根据初始值的情况,为数组指定大小长度,并依次将值填入相应的单元中,例如初始 化后temp[0][1]=2,temp[2][0]=5。 注意:等式右边大括号内嵌套的大括号不能省略,它代表数组的一行及其组成。 3.3.2 二维数组元素的引用 引用二维数组元素的方式如下: 数组名[下标1][下标2] 下标仍然是从0开始逐渐递增的,同样在引用时要注意数组的越界问题。二维数组也有 length属性,可以求每一维数组的长度。例如: int temp[][]=new int[3][5]; System.out.println(temp.length); //求二维数组的长度实际是求它的行数3 System.out.println(temp[0].length); //每个数组成员又是一个一维数组,其长度为5 【例3.3】 求二维数组中各元素的和。 package code0303; public class SumAll{ public static void main(String args[]){ int total=0; int arr[][]=new int[3][4]; for(int i=0;ic),它可以根据指定比较器Comparator 产生的顺序对对象数组进行排序。为获取Comparator 对象,可以通过方法Collator. getInstance()实现,其中参数java.util.Locale.CHINA 表示按中文语言进行排序。 Java 程序设计(第3 版) 4 8 3.5 数组实训任务 【任务描述】 编写一个模拟的Java发牌程序,要求将2副牌(即108张牌)发给4个人,并留8张底牌, 最后输出底牌和每个人手中的牌。 【任务分析】 (1)首先确定扑克牌在计算机中的表达方式,因为计算机中无法表达扑克牌中的花色,因 此最好为每张牌设定一个编号,拟定的编号规则如下: 红桃按照从小到大依次为1~13。 方块按照从小到大依次为14~26。 黑桃按照从小到大依次为27~39。 梅花按照从小到大依次为40~52。 小王为53,大王为54。 (2)由于可发的牌和每个玩家手中的牌都需要记录,且其由多个有序数据组成,因此需要 设计两个数组,以存放108张牌和每个玩家手中的牌。 (3)整个程序由以下4部分构成: ① 按照以上编号规则初始化一个包含108个数字的数组。 ② 每次随机从该数组中抽取一个数字,分配给保存玩家数据的数组。 ③ 循环输出每个玩家手中的牌。 ④ 最后输出底牌。 【任务解决】 【例3.7】 模拟发牌。 package code0305; import java.util.*; public class CardPlay{ public static void main(String[] args){ int[] total = new int[108]; //存储108 张牌的数组 int[][] player = new int[4][25]; //存储4 个玩家的牌 int leftNum = 108; //当前剩余牌的数量 int ranNumber; Random random = new Random(); //生成Random 对象,用以生成随机数 for(int i = 0;i < total.length;i++){ //初始化一维数组 total[i] = (i + 1) % 54; if(total[i] == 0){ //处理大小王编号 total[i] = 54; } } //循环发牌 for(int i = 0;i < 25;i++){//为每个人发牌 for(int j = 0;j < player.length;j++){ /生成随机下标 ranNumber = random.nextInt(leftNum); //random.nextInt 方法生成随机数 player[j][i] = total[ranNumber]; / /发 牌 total[ranNumber] = total[leftNum - 1]; //删除已经发过的牌 leftNum--; 数组 第3章 4 9 } } //循环输出玩家手中的牌 for(int i = 0;i < player.length;i++){ //通过两层循环遍历二维数组 System.out.print("玩家" + i+ "的牌:"); for(int j = 0;j < player[i].length;j++){ System.out.print(" " + player[i][j]); } System.out.println(); } //底牌 System.out.print("底牌:"); for(int i = 0;i < 8;i++){ System.out.print(" " + total[i]); } System.out.println(); } } 程序运行结果: 玩家0 的牌: 52 15 12 53 32 24 48 36 24 11 54 27 14 22 3 8 10 40 43 46 40 45 37 41 22 玩家1 的牌: 49 25 5 47 20 35 45 51 29 17 10 26 20 51 3 1 29 43 31 9 33 30 32 4 53 玩家2 的牌: 42 7 13 38 34 50 12 6 39 49 33 23 14 31 7 19 39 48 16 18 35 5 41 9 11 玩家3 的牌: 44 2 30 26 28 46 44 19 21 23 25 21 15 13 1 28 34 52 4 8 6 47 17 2 27 底牌: 50 42 18 37 16 38 36 54 1.为了定义3个整型数组a1、a2、a3,下面声明正确的语句是哪一个? A.intArray[]a1,a2; inta3[]={1,2,3,4,5}; B.int[]a1,a2; inta3[]={1,2,3,4,5}; C.inta1,a2[]; inta3={1,2,3,4,5}; D.int[]a1,a2; inta3=(1,2,3,4,5); 2.编程实现两个同行列数矩阵的加法运算。 3.将给定数组inta[]={78,23,56,34,12,45,67,89}按从小到大顺序进行排序并输出。 4.给出下列程序段运行的结果: public static void main(String args[]) { int array[]={1,2,3,4,5}; printarray(array); could_modify(array); printarray(array); } Java 程序设计(第3 版) 5 0 static void could_modify(int a[]){ for(int i=0;i