一维数组
1.单个的数组变量可以引用一个大的数据集合。Java和许多高级语言都提供了一种乘坐数组(array)的数据结构,可以用它来存储一个元素个数固定且元素类型相同的有序集。
2.数组的基础知识
一旦数组被创建,它的大小是固定的。使用一个数组引用变量,通过下标来访问数组中的元素。数组是用来存储数据的集合。
-
2.1声明数组变量
elementType[] arrayRefVar;(元素类型[] 数组引用变量;)
elementType可以是任意数据类型,但是数组中所有元素都必须具有相同的数据类型。 -
2.2创建数组
不同于基本数据类型变量的声明,声明一个数组变量时并不在内存中给数组分配任何空间。它只是创建一对数组的引用的存储位置。如果变量不包含对数组的引用,那么这个变量的值为null。除非数组已经被创建,否则不能给它分配任何元素。声明数组后,可以使用下面的语法用new操作符创建数组,并且将它的引用赋给一个变量:arrayRefVar = new elementType[arraySize];
使用new elementType[arraySize]创建了一个数组;把这个新创建的数组的引用赋值给变量arrayRefVar。
声明一个数组变量、创建数组、然后将数组引用赋值给变量这三个步骤可以合并在一句里:
elementType[] arryRefVar[] = new elementType[arraySize];
(元素类型[] 数组引用变量=new 元素类型[数组大小]?
使用以下语法给这些元素赋值:
arrayRefVar[index]=value;
一个数组变量看起来似乎是存储了一个数组,但实际上它存储的是指向数组的引用。严格上讲一个数组变量和一个数组是不同的,但大多数情况他们的差别可以忽略不计。
-
2.3数组大小和默认值
当给数组分配空间时,必须指定该数组能够存储的元素个数,从而确定数组大小。创建数组之后就不能再修改它的大小。可以使用arrayRefVar.length得到数组的大小。当数组创建后,它的元素被赋予默认值,数值型基本数据类型的默认值是0,char型的默认值为‘\u0000’、boolean型的默认值为false。 -
2.4访问数组元素
数组元素可以通过下标访问。其范围从0开始到arrayRefVar.length-1结束。
数组中每个元素都可以I使用下面的语法表示,称为下标变量(index variable);
arrayRefVar[index];(数组引用变量[下标]?
数组创建后,下标变量与正常变量的使用方法相同。 -
2.5数组初始化语法
将声明数组、创建数组和初始化数组结合到一条语句中:
elementType[] arrayRefVar={value0,value2,…,valuek};(元素类型[] 数组引用变量={值0,值1,…,值k}?
数组初始化语法中不使用操作符new。使用数组初始化时,必须将声明、创建和初始化数组都放在一条语句中。将他们分开产生语法错误。 -
2.6处理数组
处理数组元素时,经常会用到for循环,原因是:(1)数组中所有元素都是同一类型的。可以使用循环以同样的方式反复处理这些元素。(2)由于数组的大小是已知的,所以很自然地就使用for循环。 -
2.7foreach循环
Java支持一个简便的for循环,称为foreach循环,即不使用下标变量就可以顺序地遍历整个数组。
例如:下面代码就可以显示数组mylist的所有元素:for(double e:my list){
System.out.println(e);
}
此代码可以读作“对mylist中每一个元素e进行以下操作”。注意,变量e必须声明为与mylist中元素相同的数据类型。
通常,foreach循环的语法为:
for(elementType element:arryRefVar){
//Process the element
}
但是,当需要以其他顺序遍历数组或改变数组中的元素时,还是必须使用下标变量。
警告:越界访问数组是经常会出现的程序设计错误,它会抛出一个运行错误ArrayIndexOutOfBoundException.为了避免错误的发生,在使用时应确保所使用的下标不超过arrayRefVar.length-1.
3.数组的复制
要将一个数组中的内容复制到另外一个中,需要将数组的每个元素复制到另外一个数组中。如:
list2=list1;
该语句并不能将list引用的数据内容复制给list2,而只是将list1的引用值复制给了list2.在这条语句之后,list1 和list2都指向同一个数组。list2原先所引用的数组不能再引用,他就变成了垃圾,会被Java虚拟机自动回收(这个过程成为垃圾回收)。
在Java中,可以使用赋值语句复制基本数据类型的变量,但不能复制数组。将一个数组变量赋值给另一个数组变量,实际上是将一个数组的引用复制给另一个变量,使两个变量都指向相同的内存地址。
复制数组有三种方法:
(1)使用循环语句逐个地复制数组的元素。
(2)使用System类中的静态方法arraycopy。
(3)使用clone方法复制数组。
可以使用循环将源数组中的每个元素复制到目标数组中的对应元素。例如,下述代码使用for循环将sourceArray复制到targetArray:
int[] sourceArray={2,3,1,5,10};
int[] targetArray=new int[sourceArray.length];
for(int i=0;i<sourceArray.length;i++){
targetArray[i]=sourceArray[i];
}
另一种方式是使用java.lang.System类的arraycopy方法复制数组,而不是使用循环。arraycopy的语法如下所示:
arraycopy(sourceArray,srcPos,targetArray,tarPos,length);
其中,参数srcPos和tarPos分别表示在源数组sourceArray和目标数组targetArray中的起始位置。从sourceArray复制到targetArray中的元素个数由参数length指定。例如,可以使用下面的语句改写上述循环:
System.arraycopy(sourceArray,0,targetArray,0,sourceArray.length);
arraycopy方法没有给目标数组分配内存空间。复制前必须创建目标数组以及分配给它的内存空间。复制完后,sourceArray和targetArray具有相同的内容,但占有独立的内存空间。
注意:arraycopy方法违背了Java命名习惯。根据命名习惯,该方法应该命名为arrayCopy(即字母C大写)。
4.将数组传递给方法
当将一个数组传递给方法时,数组的引用被传给方法。正如前面给方法传递基本数据类型的值一样,也可以给方法传递数组。例如,下面的方法显示int型数组的元素:
public static void printArray(int[] array){
for(int i=0;i<array.length;i++){
System.out.print(array[i]+" ");
}
}
可以通过传递一个数组调用上面的方法。例如,下面的语句调用printArray方法显示3,1,2,6,4,2:
printArray(new int[] {3,1,2,6,4,2});
注意:前面的语句使用下述语法创建数组:
new elementType[] {value0,value1,...,valuek};
该数组没有显式地引用变量,这样的数组称为匿名数组(anonymous array)。
Java使用按值传递(pass-by-value)的方法将实参传递给方法。传递基本数据类型变量的值与传递数组值有很大的不同。
对于基本数据类型参数,传递的是实参的值。
对于数组类型参数,参数值 是数组的引用,给方法传递的是这个引用。从语义上来讲,最好的描述就是参数传递的是共享信息(pass-by-sharing),即方法中的数组和传递的数组是一样的。所以,如果改变方法中的数组,将会看到方法外的数组也变化了。
注意:数组在Java中是对象。JVM将对象存储在一个称作堆(heap)的内存区域中,堆 用于动态内存分配。
5.从方法中返回数组
当从方法中返回一个数组时,数组的引用被返回。
可以在调用方法时向方法传递一个数组。方法也可以返回一个数组。
6.可变长参数列表
具有同样类型的可变长度的参数可以传递给方法,并将作为数组对待。
可以把类型相同但个数可变的参数传递给方法。方法中的参数声明如下:
typeName…parameterName(类型名…参数名)
在方法声明中,指定类型后紧跟着省略号(…)。只能给方法中指定一个可变长参数,同时该参数必须是最后一个参数。任何常规参数必须在它之前。
Java将可变长参数当成数组对待。可以将一个数组或数目可变的参数传递给可变长参数。当用数目可变的参数调用方法时,Java会创建一个数组并把参数传给它。
7.数组的查找
如果一个数组拍好序了,对于寻找数组中的一个元素,二分查找比线性查找更加高效。
查找是在数组中寻找特定元素的过程,例如:判断某一特定分数是否包括在成绩列表中。查找是计算机程序设计中经常要完成的任务。有很多用于查找的算法和数据结构。线性查找(linear searching)和二分查找(binary searching)。
- 7.1线性查找法
线性查找法将要查找的关键字key与数组中的元素逐个进行比较。这个过程持续到在列表中找到与关键字匹配的元素,或者查完列表也没有找到关键字为止。如果匹配成功,线性查找返回与关键字匹配的元素在数组中的下标。如果没有匹配成功,则返回-1.
线性查找法把关键字和数组中的每一个元素进行比较。由于线性查找法的执行时间随着数组元素个数的增长而线性增长,所以,对于大数组而言,线性查找法的效率并不高。 - 7.2二分查找法
二分查找法是另一种常见的对数值列表的查找方法。使用二分查找法的前提条件是数组中的元素必须已经拍好序。假设数组已经按升序排列。二分查找法首先将关键字与数组的中间元素进行比较。考虑下面三种情况:
(1)如果关键字小于中间元素,只需要在数组的前一半元素中继续查找关键字。
(2)如果关键字和中间元素相等,则匹配成功,查找结束。
(3)如果关键字大于中间元素,只需要在数组的后一般元素中继续查找关键字。
8.数组的排序
如同查找一样,排序是计算机编程中非常普遍的一个任务。对于排序已经开发出很多不同的算法。选择排序、冒泡排序、插入排序。