第 4章 数组
数组是经常使用的一个工具对象,说它是工具是因为在编写程序时经常使用其良好的数据组织特性(一种数据结构),说它是对象是因为在 Java
中数组是一种动态创建的对象,它包含很多变量,
但要求变量的数据类型必须一致。数组中的数据元素没有名称,而是通过一种特殊的访问方式即数组下标来访问数组中的元素值。数组按维数分为一维数组、多维数组,而多维数组中最常用的是二维数组,本章按照这种分类方式分别介绍一维数组、二维数组和多维数组。
4.1 一维数组
一维数组是具有相同数据类型数据的一种线性组合,这里数据类型可以是 Java定义的任意一种数据类型,包括对象引用类型即对象的引用,数组中可以存放相同类的多个对象。本节按照定义一维数组、初始化一维数组和一维数组的使用依次讲解一维数组。
4.1.1 定义一维数组
一维数组的定义方式是:
datatype arrayName[ ] 或 datatype[] arrayName;
其中 type为任意数据类型,数组中的数据元素也是 type类型,
arrayName是数组名称,在编写程序时该名称应该具有一定的意义。 []
是数组的标识符,此时定义了一个数组,但数组中没有数据元素,也就是说 Java允许定义一个数组但数据元素的数量为 0,通常称这样的数组为空数组。空数组没有获得内存空间,所以无法使用,必须 new
关键字为数据分配内存空间如下例子所示。
arrayName = new arrayName[size];
在 Java中 new关键字的作用是产生该类的某个对象,并为该对象分配内存空间,内存空间的大小视对象大小而定,如一个 double类型的浮点数据对象肯定比 int类型的整型数据对象分配的内存空间更大。下面举例定义 int 型数组。
int IntArrayExample = new int[100];
这里 int是声明了数组中元素的数据类型,数组名字是
IntArrayExample。 new关键字为该数据类型分配内存空间,空间大小是 100个整型 int型数据的大小,即 4(字节) *100 = 400字节的内存空间。
4.1.2 初始化一维数组
用 new关键字为数组分配了存储空间后,对于数组中的元素
,到底是什么,仍然无法确定,所以需要为已经分配了存储空间的数组填充相应的数据,这就是数组初始化的作用。
一维数组初始化的格式:
datatype arrayName = new type[value1,value2,value3];
在数组标符 []内是 type类型的数组值,这里初始化了一个类型为 type的一维护数组,数组中包含 3个 type数据类型的数据元素,数据值依次是 value1,value2,value3,数据值之间使用,,”隔开,这里的,,”是在英文输入法下输入的,
如果是其它输入法输入,在编译期会发生编译错误提示。
当然也可以先定义数组,定义后再初始化数组如:
datatype arrayName[];
arrayName = new datatype[value1,value2,value3];
4.1.3 使用一维数组
在定义和初始化了数组后,就可以使用数组进行数组的使用,这里,使用,主要强调对数组中数据元素的操作。在本章开始处提到数组元素的获得通过一种特殊的方式,即通过下标访问数组元素,如果数组的长度为 n则可通过从 0到 n-1的整数索引获得相应位置的元素,数组元素的第一个值的整数索引为 0,即 IntArray[0]表示数组的第一个数据元素。如数组 IntArray,
int IntArray[] = {19,78,4,18,77};
数组包含 5个数据元素,其中 IntArray[0]=19,
IntArray[4]=77。
4.2 二维数组
二维数组是多维数组的一种,这里单独介绍二维护数组是因为它是编写程序时使用频率最高的一类多维数组。从三个方面介绍二维数组,分别是定义二维数组、初始化二维数组和如何使用二维数组。相信读者通过本节的学习可以轻松应用二维数组这个有用的工具编写程序。
4.2.1 定义二维数组
二维数组的定义方式是:
datatype arrayName[][];或 datatype[][] arrayName;
这里定义了一个二维数组,其中的数据类型为 datatype,
二维数组名为 arrayName,[][]是二维数组的标识符。同样,
这里的数组没有实际用处,因为并没有为其分配内存空间,
此时,需要 new关键字实现二维数组的内存分配。其实现方式是:
arrayName[][] = new datatype[rowsize][columnsize];
datatype是二维数组中所存放数据的数据类型,rowsize是二维数组的行的数量,columnsize是二维数组的列的数量。
通常二维数组的行的长度称为二维数组的长度。这样为二维护数组分配了 rowsize*columnsize个内存空间,可以存放 datatype类型的数据。例如:
int IntArray[][] = new int[2][3];
4.2.2 初始化二维数组
二维数组的初始化是指在定义并为其分配了合适的内存空间后,
为每个存储空间填充数据。使得数组有可以操作的实际数据对象。
二维数组的初始化有两种方式一种是在定义时初始化,一种是在定义完后为每一个位置赋予数据元素。
( 1)在定义时初始化二维护数组。该方式也称为静态初始化,其初始化格式如下例所示:
Int IntArray[][]={{1,2,3},{6,5,4}};
( 2) 直接赋予初值方式初始化二维护数组 。 如下定义了一个数组
IntArray[][]。
1 Int IntArray[][] = new int[10][10]; //定义数组并为数组分配内存空间
2 for(int i=0;i<10;i++){ // 通过两个循环为数组赋值
3 for(int j=0;j<10;j++){
4 IntArray[i][j]=i*j;
5 }
6 }
4.2.3 使用二维数组
二维数组通过两层嵌套来获得数组中的数据,再进行其他运算,当然也可以获得数组中的单独数据。代码创建二维数组示例详细地说明了二维数组的使用。
代码说明二维数组的各种创建方式,包括静态初始化一个常规数据类型、静态初始化对象数组和逐渐构建二维数组,通过三种常用的数组创建方式,读者可以体会和理解不同数据类型的静态和动态创建方式。
4.3 多维数组
多维数组指三维以上的数组,上节读者详细了解了二维护数组,不难看出如果想提高数组的维数,
只需要声明数组时增加下标,再增加中括号即可,
如定义四维护数组可以在定义二维数组上扩展为
double d[][][][],更多维数组的声明方式依此类推。多维数组的使用与一维、二维数组相类似。
不过每增加一维,则增加一层嵌套,所以对于多维数组,使用起来相对复杂。
4.3.1 定义多维数组
在定义多维数组前必须先声明数组,这样就明确了数据类型和数组名,以三维数组为例,其格式如下:
数据类型 多维数组名 [][][];
数据类型 [][][] 多维数组名
[][][]是三维数组的标志,其位置如多维数组声明格式所示。如:
1 String multiStringArray[][][]; //数组标志在数组名后
2 String[][][] multiStringArray; //数组标志在数据类型后
3 byte multiByteArray[][][]; //数组标志在数组名后
4 byte[][][] multiByteArray; //数组标志在数据类型后
4.3.2 初始化多维数组
无论是一维数组还是多维数组,数组初始化的本质是一样的,就是为分配了内存空间的数组填充具体的数据元素。
这样的数组才有用。
数据元素分两种,一是对象类型,一是基本数据类型。如果是对象类型首先需要对象的初始化,否则该数组中的对象数据就无法使用。如果是基本类型,Java初始化为默认值。多维数组的初始化也有两种:
( 1) 静态初始化
多维数组的静态初始化是在定义数组时进行数据的初始化 。
Int ThreeDemisionArray =
{{{1,2},{3,4}},{{5,6},{7,8}}};
( 2)赋值初始化,在定义了多维数组后(声明并定义了内存空间),系统每个内存空间赋予数据元素的值。
4.3.3 使用多维数组
数组的使用就是通过下标来获取数据元素的值或通过数组元素的下标修改相应数据的值,多维数组的使用也是如此 。
代码实现访问多维数组的数据元素,该程序依次获得多维数组的数据元素并且按照维数依次输出 。
显然,一旦获得数组中数据元素后可以实现数据的各种操作,而不单是打印输出结果 。
代码 访问多维数组元素示例
1 class MultiArrayTest{
2 public static void main(String[] args){
3 int multiArray[][][] = new int[3][4][5]; //声明和初始化数组 multiArray[][][]
4 for(int i = 0 ;i <3;i++){
//6,7,8,9行通过三重循环为数组赋值
5 for(int j = 0 ;j<4;j++){
6 for(int k=0;k<5;k++){
7 multiArray[i][j][k] = i*j*k;
8
System.out.print(multiArray[i][j][k]+" ");
9 }
10 System.out.println();
//实现分行显示
11 }
12 System.out.println();
//实现分行显示
13 }
14 }
15}
4.4 数组操作
本节介绍的数组操作在运用数组中经常用到,数组操作表现为具体的方法,这些方法供开发人员调用。这些实现数组操作的方法都是静态
( static)方法,可以直接调用。如果这些方法的参数为具体的数组引用而该引用为空,数组都将抛出 NullPointerException异常。本节重点介绍数组的复制、数组的填充、数组的比较,数组排序和在数组中搜索。
4.4.1 数组的复制
数组的复制通过类 Arrays 的静态方法 copyOf(type[]
original,int length)实现的,其中 type可以是 boolean
类型,int类型,short类型,char类型,byte类型等 。
代码说明如何实现数组的复制,以参数为 char型的数组为例 。
代码 char类型数组的拷贝示例
1 char charArrayCopy[] = {‘h’,’e’,’l’,’l’,’o’};
2 //对数组 charArrayCopy进行复制,新数组的长度为 4,
截去 charArrayCopy中的多余元素 。
3 Arrays.copyOf(charArrayCopy,4);
4 //对数组 charArrayCopy进行复制,新数组长度为 8,
以 null字符填充,其中
5 //charArrayCopy的数组长 度为 4,新数组的其余部分用 null字符填充 。
6 Arrays.copyOf(charArrayCopy,8);
4.4.2 数组的填充
数组的填充实现了数组部分或全部空间的填充,Java提供了一种方法两种形式,一种形式是 fill(type[] a,type
b);一种形式是 fill(type[] a,int key1,int key2,type
b);前者表示把数组 a的全部空间填充为 b,后者表示把数组 a的从 key1到 key2的全部内容填充为 b,但不包含 key2的位置。下面代码详细说明这两种形式的具体用法。
1 char charArrayOne[] = {‘a’,’b’,’c’,’d’,’e’,’f’};
2 char charArrayTwo[] = new char[5];
3 //把 char类型的数组 charArrayOne的第四和第五个位置的元素填充为 ’ t’
4 Arrays.fill(charArrayOne,4,6,’t’);
5 //把 char类型的数组 charArrayTwo的所有元素填充为 ’ p’
6 Arrays.fill(charArrayTwo,’p’);
4.4.3 数组的比较
数组的比较是对两个数据类型相同的数组而言的,实现比较的函数为 equals(数组 1,数组 2)。如果两个数组的数据元素数量相同,
相同位置上的数据元素又相等。则这两个数组相等,函数返回
boolean值 true,否则不相等,函数返回 boolean值 false。
1 char charArray1[] =
{‘a’,’b’,’c’,’e’,’f’,’g’,’h’,’I’,’j’,’k’}
2 char charArray2[] =
{‘a’,’b’,’c’,’e’,’f’,’g’,’h’,’I’,’j’,’k’}
3 double doubleArray1[] ={12.0,99.43,33,2,22,56.9}
4 double doubleArray2[]={12.0,99.43,33}
5 Arrays.equals(charArray1,charArray2); //返回 true,类型和数量相同
6 Arrays.equals(charArray1,doubleArray1); //返回 false,元素类型不同
7 Arrays.equals(doubleArray1,doubleArray2); //返回 false,元素数量不同
4.4.4 数组的排序
数组的排序指依据数组中的数据类型升序排序,如果是整数则按照从小到大的顺序,如果是字符( char)类型则按照字母升序排列。数组的排序方法为静态方法,可以直接调用。该方法有两种参数格式,一是 sort(数组引用 );二是 sort(数组引用,参数 1,参数 2);前者对整个数组升序排序,
而后者对数组中的一个范围内的元素排序,参数 1是起始位置,参数 2是截止位置,但不包含该位置。
代码实现了 char类型数组的排序并打印排序结果。
4.4.5 数组的查找
数组的查找实现在指定数据类型的数组中查找一个具体的元素,如在 int型数组中查找一个整数,如果该整数存在,
则输出该整数在数组中的位置,需要注意数组中元素的位置是从 0开始记数的,如果该整数不存在则输出一个负数。
在 Java的数组( Arrays)操作中使用二分查找算法实现数组中元素的查找。
代码实现在 int型数组中查找一个具体的元素。如果该元素存在则打印该元素的位置,如果不存在打印,指定数据元素不存在,。
4.5 本章习题
( 1)学完本章后,读者需要回答:
1.什么是数组?数组的特点?创建数组的基本步骤?
2.编写一个声明 10行 10列的数组语句。
3.编写一个程序,读取键盘输入的 26个英文字符,并按照逆序输出。
4.计算 10-20的整数的平方,并将结果保存在一个数组中。
( 2)注意事项:
1.使用数组一定要先声明再初始化,对于基本类型的数组可以使用默认初始化,此时数组也可以使用(没什么意义),对于对象类型数组则必须初始化数组,使得数组中包含实例对象。
2.使用多维数组时,一定把握不要使用三重以上的循环,
如果出现最好拆解成多个三重以下的循环,以减少程序的复杂度,提高程序的可读性。