Java中关于数组的一些知识点
一、数组(一维):
对于声明变量,int score1 = 81; 等等这些操作,如果我们有四个成绩,是不是可以定义变量score 1、2、3、4呢?但是,如果我们要定义400个成绩又当如何呢?
这就可以用到数组了,数组可以指定一个长度,然后在数组里可以存放这个长度范围的同类型元素,可以将数组理解为是一个巨大的“盒子”,里面可以按顺序存放多个类型相同的数据。不过,因为它是由长度范围的,所以长度在声明完成之后就是不能变化的了,对于一些总是需要增加一些信息进去的情况,就不适合于用数组了。如电话簿。你也许会想,能不能一开始就声明一个很长很长的长度用来放数据,但是声明很长是需要占内存的,会拖慢程序的运行速度。(对于这一"缺点",会在之后的集合中得到很好的应用)
那么,如何使用 Java 中的数组?Java 中操作数组只需要四个步骤:
1、 声明数组
语法: 数据类型[ ] 数组名; 或者 数据类型 数组名[ ];
其中,数组名可以是任意合法的变量名,如:
int[] scores;
double aArray[];
String[] names;
2、 分配空间
简单地说,就是指定数组中最多可存储多少个元素
语法: 数组名 = new 数据类型 [ 数组长度 ];
其中,数组长度就是数组中能存放元素的个数,如:
scores = new int[5];
aArray = new double[5];
names = new String[5];
其实,我们也可以将上面的两个步骤合并,在声明数组的同时为它分配空间,如:
int[] scores = new int[5];
关于该分配空间的过程是一个动态创建数组的过程
3、 赋值
分配空间后就可以向数组中放数据了,数组中元素都是通过下标来访问的,并且注意的是数组中的索引(即下标)是从0开始,到数组长度-1结束。例如向 scores 数组中存放学生成绩
scores[0] = 81;
scores[1] = 85;
scores[2] = 87;
scores[3] = 89;
scores[4] = 92;
4、 处理数组中数据
我们可以对赋值后的数组进行操作和处理,如获取并输出数组中元素的值
System.out.println("scores数组中的第一个元素是: " + scores[0]);
在 Java 中还提供了另外一种直接创建数组的方式,它将声明数组、分配空间和赋值合并完成,关于此种方式,称做静态创建数组。语法格式为:
数据类型 数组名[] = { 需要给数组赋值的内容(多个以逗号隔开) }; 如:
int scores[] = {81, 85, 87, 89, 92};
它等价于:
int[] scores = new int[]{81, 85, 87, 89, 92};
二、下面再介绍一些关于数组的基本操作:
- 遍历数组:
关于遍历数组主要有一维和二维两种,分别以for循环和foreach循环进行遍历。代码如下:
package com.rocking; public class TraverseArray { public static void main(String[] args) { // TODO Auto-generated method stub int a[] = new int[]{1, 2, 3, 5, 98, 45, 15 ,546 , 49}; int aa[][] = new int[][]{{12, 26, 56}, {15, 65, 48, 89}, {45, 29, 75, 64, 19}}; //遍历一维数组(for 与 foreach两种方式) for (int i = 0; i < a.length; i++) { System.out.print(a[i]+" "); }
System.out.println("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>"); for (int i : a) { System.out.print(i+" "); }
System.out.println("\n/////////////////////////////"); //遍历二维数组(for 与 foreach两种方式) for (int i = 0; i < aa.length; i++) { for (int j = 0; j < aa[i].length; j++) { System.out.print(aa[i][j]+" "); } }
System.out.println("\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); for (int[] i : aa) { for (int j : i) { System.out.print(j+" "); }
} } }
可以看到,foreach语句进行遍历稍微简单一些。如果要引用数组或者集合的索引,则foreach语句无法做到,foreach仅仅老老实实地遍历数组或者集合一遍
关于foreach语句,需要将Compiler Compliance Level调成1.5或以上的等级。默认的是1.4;否则使用foreach语句会报如下的错误。[Syntax error, 'for each' statements are only available if source level is 1.5 or greater]。具体操作为:右键你建立的项目名,选择最下面的Properties,在打开的面板中选择Java Compiler。将右边JDK Compliance下的复选框取消选中,再将Compiler Compliance Level的等级调成1.5或以上,点击OK即可。
- 填充替换数组元素:
数组中的元素定义完成之后,可以通过Arrays类提供的fill()方法来对数组中的元素进行替换。该方法通过各种重载的形式可完成任意类型的数组元素的替换。
fill()方法有如下两种参数类型,①、fill(int[] a, int value)和②、fill(int[] a, int fromIndex, int toIndex, int value).
方法①可以将指定的int值分配给int型数组的每个元素;方法②将指定的int值分配给int型数组指定范围中的每个元素。指定的范围是从索引fromIndex(包括)一直到索引toIndex(不包括)。如果fromIndex == toIndex,则填充范围为空。如果指定的索引位置大于或等于要进行填充的数组的长度,则会报出ArrayIndexOutOfBoundsException(数组越界异常)
代码如下:
package com.rocking;
import java.util.Arrays;
public class LearnArrayFill {
public static void main(String[] args) {
// TODO Auto-generated method stub
int a[] = new int[]{1, 2, 3, 5, 98, 45, 15 ,56 , 49};
Arrays.fill(a, 6); //将数组中的所有元素都替换为value的值6
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]+" ");
}
System.out.println();
int b[] = new int[]{98, 3, 5, 45, 15 ,46 ,1, 2, 49};
Arrays.fill(b, 3, 5, 99); //将数组a中的a[3](包括第4个)到a[5](不包括第6个)之间的元素替换为value的值6
for (int i : b) {
System.out.print(i+" ");
}
}
}
- 对数组进行排序:
通过Arrays类提供的静态方法sort()即可实现对指定类型数组按数字升序进行排序。
主要有以下两种重载方式:
①、sort(Object[] a)
该形式是以升序的方式对数组中的所有元素进行排序。
②、sort(Object[] a, Object fromIndex, Object toIndex)
该形式是将索引位置从fromIndex(包括)到toIndex(不包括)内的元素按照升序的顺序进行排序。
import java.util.Arrays;
public class LearnArraysSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
int array[] = new int[]{98, 3, 5, 45, 15 ,46 ,1, 2, 49};
int[] a = {98, 3, 5, 45, 15 ,46 ,1, 2, 49};
Arrays.sort(array); //使用sort(Object[] array)重载形式,将数组中的所有元素按照升序的顺序排序
for (int i = 0; i < array.length; i++) {
System.out.print(array[i]+">>");
//1>>2>>3>>5>>15>>45>>46>>49>>98>>
}
System.out.println("\n\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
Arrays.sort(a, 3, 6); //将索引位置从fromIndex(包括)到toIndex(不包括)内的元素按照升序的顺序进行排序。
for (int i : a) {
System.out.print(i+"<<");
//98<<3<<5<<15<<45<<46<<1<<2<<49<<
}
System.out.println("\n\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
String aa[] = {"AAB", "AAb", "aaB", "535", "001", "纳尼", "嗦嘎", "aab"};
Arrays.sort(aa);
for (String str : aa) {
System.out.print(str+"///");
//001///535///AAB///AAb///aaB///aab///嗦嘎///纳尼///
}
}
}
在上述代码中,String类型的数组的排序算法是按照字典编码顺序排的,因此我们可以看到:数字排列在字母的前面,字母排列在汉字的前面;并且大写字母排列在小写字母的前面。
- 复制数组:
对数组进行复制,需要用到Arrays类的copyOf()或copyOfRange()方法;
copyOf(Object[] original, int newLength):复制数组到指定的长度。
copyOfRange(Object[] original, int fromIndex, int toIndex):将指定数组的指定长度复制到另一个新的数组中。
关于复制就有粘贴,所以这些数组调用了复制的方法,就需要有一个新的数组来接收它。
一言不合就贴代码:
import java.util.Arrays;
public class LearnArraysCopy {
public static void main(String[] args) {
// TODO Auto-generated method stub
int array11[] = new int[]{98, 3, 5, 45, 15 ,46 ,1, 2, 49};
String array21[] = {"AAB", "001", "纳尼", "aaB", "535", "嗦嘎", "aab", "AAb"};
//将数组array21中的长度为5的数组元素复制到新的数组array22中
String[] array22 = Arrays.copyOf(array21, 5);
for (String str : array22) {
System.out.print(str+"<<>>");
//AAB<<>>001<<>>纳尼<<>>aaB<<>>535<<>>
}
System.out.println("\n\n+++++++++++++++++++++++++++++++++++++++\n");
//将数组array11中的索引位置3(包括)到7(不包括)的元素复制到新的数组array12中
int[] array12 = Arrays.copyOfRange(array11, 3, 11);
for (int i = 0; i < array12.length; i++) {
System.out.print(array12[i]+">><<");
//45>><<15>><<46>><<1>><<2>><<49>><<0>><<0>><<
}
}
}
可以看到:我们可以将toIndex(newLenght)的数值设置为大于数组的长度,那么在新数组中就会以0(null)代替后面没有的元素,但是,如果将fromIndex设置为大于数组长度的值,就会报ArrayIndexOutOfBoundsException(数组越界异常)
- 数组查询:
对数组中元素的查询可以用二分搜索法来搜索指定类型的数组,以获得指定的值。不过使用二分查找法必须先对数组进行排序。如果没有对数组进行排序,则结果是不确定的。如果数组包含多个带有指定值的元素,则无法保证找到的是哪一个。
所以我们可以建立一个程序,如:LearnBinarySearch。然后在其中创建一个数组,首先调用Arrays类的sort()方法对数组进行排序。然后使用binarySearch()对key值进行查找。
如果数组中存在这个key值,那么就返回该key值所在的索引值。如果key值不在,那么就返回第一次大于该key值的数值所在位置(从1开始)的负值,注意此处说的是位置,从1开始;而不是索引的值(从0开始)。
当然,如果我们不先对数组进行排序又会怎么样呢?创建了一个数组 int array1[] = new int[]{98, 16, 9, 45, 13 ,46 ,1, 4, 49}; 然后分别对其中的每一个元素进行二分查找,返回的值只有13是返回一个4以及49返回一个8;其他的都是返回负值,然后不存在的数值返回的也是乱七八糟的负值。似乎没有规律可循。
package com.rocking;
import java.util.Arrays;
public class LearnBinarySearch {
public static void main(String[] args) {
// TODO Auto-generated method stub
//创建一个一维数组
int array1[] = new int[]{98, 16, 9, 45, 13 ,46 ,1, 4, 49};
//首先对数组进行排序
Arrays.sort(array1);
//遍历数组,查看现在数组的排序顺序(方便在后面比较查找的数值的索引值)
for (int i = 0; i < array1.length; i++) {
System.out.print(array1[i]+" ");
}
System.out.println("\n\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
//如果存在该数值,则返回一个查到的Key值的索引值
System.out.println(Arrays.binarySearch(array1, 46));
System.out.println("\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
//如果数组中不存在该数值,则返回第一次大于该key值的数值所在位置(从1开始)的负值(注意是位置值而不是索引值)
//因为数组中的所有元素都比-5要大,所以返回的是数组中第一个元素的位置的负值,即-1
System.out.print(Arrays.binarySearch(array1, -5)+" ");
//第一次大于7的数值是9,处于第3位;于是返回-3
System.out.print(Arrays.binarySearch(array1, 7)+" ");
//第一次大于33的数值是45,处于第6位;于是返回-6
System.out.print(Arrays.binarySearch(array1, 33)+" ");
//第一次大于120的数值在数组中不存在,于是返回最大位置值+1的负值,即-10
System.out.println(Arrays.binarySearch(array1, 120)+" ");
System.out.println("\n<<<<<<<<<<<<<<>>>>>>>>>>>>>>\n");
NoSort ns = new NoSort();
ns.method();
}
}
class NoSort {
//在该方法中测试一下如果不先对数组进行排序,而进行二分查找会出现什么结果
void method() {
int array1[] = new int[]{98, 16, 9, 45, 13 ,46 ,1, 4, 49};
System.out.println(Arrays.binarySearch(array1, 46));
System.out.println("\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
System.out.print(Arrays.binarySearch(array1, 7)+" ");
System.out.print(Arrays.binarySearch(array1, 33)+" ");
System.out.println(Arrays.binarySearch(array1, 47)+" ");
}
}
上述过程中用到的只是binarySearch()方法的一种重载形式,它还有一种重载形式是指定范围内的查找;语法如下:
binarySearch(Object[] array, int fromIndex, int toIndex, Object key);
其中的array是数组名;fromIndex是开始查找的开始处索引值(包括);toIndex是查找的结束处索引值(不包括);key是要查找的元素
官方文档中提到,使用该方法同样需要先进行排序
package com.rocking;
import java.util.Arrays;
public class LearnBinarySearch2 {
public static void main(String[] args) {
int array1[] = new int[]{98, 16, 9, 45, 13 ,46 ,1, 4, 49};
Arrays.sort(array1);
int i = Arrays.binarySearch(array1, 2, 8, 46);
for (int j = 0; j < array1.length; j++) {
System.out.print(array1[j]+" ");
}
System.out.println("\n46所处的索引位置是:"+i);
}
}
注意:如果指定的范围大于或等于数组的长度,会报出[ArrayIndexOutOfBoundsException]数组越界异常。
三、下面介绍一些关于数组的排序算法:
- 冒泡排序:
冒泡排序排序元素的过程总是将小数往前放,大数往后排;类似于水中上升的气泡,故作冒泡排序。
基本思想:比较相邻的元素值,如果两个元素前面的比后面的大,则将前面的小数往后排,后面的大数往前移。具体的原理图就不画了(贴个关于冒泡排序的动画效果的网址http://student.zjzk.cn/course_ware/data_structure/web/flashhtml/maopaopaixu.htm)。再唠叨一下程序的原理好了。
冒泡排序用到了双重的for循环。其中外层循环是用于控制排序的轮数的,最多需要的是数组长度-1轮。内层循环是用于比较相邻元素之间的数值大小,如果前面的元素大于后面的元素,则进行交换。对比的次数是和轮数有关的,每一轮的对比次数是不会超过数组长度-轮数的大小的。好了,又到了大家最喜欢的贴代码的环节了。代码如下:
package com.rocking;
public class MaoPao {
public static void main(String[] args) {
int score[] = {85, 90, 87, 100, 89, 81, 82, 92};
int temp;
for (int i = 1; i < score.length; i++){ //最多做n-1趟排序
for(int j = 0 ;j < score.length - i; j++){ //每一个数最多进行数组长度-1-排列的趟数
//升序过程,
if (score[j] > score[j+1]) {//如果前面的数值大于后面的数值,则将前面的数值换到后面的位置,而将后面的元素换到前边的位置,因此需要添加一个temp变量用来转换两个位置的数
temp = score[j];
score[j] = score[j+1];
score[j+1] = temp;
}
}
for(int j = 0; j<score.length; j++) {
System.out.print(score[j] +" ");
}
System.out.println();
}
}
}
- 直接选择排序:
直接选择排序听名字就知道其是选择排序的一种,其排序速度比冒泡排序要快一些。
基本思想:在一个无序数组中,首先从前面第一个数开始,依次与后面的数值进行比较,假如是按从小到大的顺序排列,则从前依次往后比较之后,不断的用比较得到的新的最大的与后面的数进行比较。最终将两两比较后找到的最大的数值与最后一位数的位置进行互换。相当于是从数组中找到其中最大的一个数,将其位置与最后一位进行交换。然后除最末这个最大的数值,前面的数值又是一个无序组,在该无序组中,又找出最大的数值,与该无序组的最后一个数值进行位置交换,从而又在前面产生一个新的无序组。重复以上步骤,最终得到了一个从小到大排列的数组。同样贴上一个关于快速选择排序算法的网址http://student.zjzk.cn/course_ware/data_structure/web/flashhtml/zhijiexuanze.htm
根据其基本思想,可知其与冒泡排序类似,也是最多进行数组长度array.length - 1轮排序,且每次排序需要比较的不超过array.length - i(轮数)次。因此,该算法依旧是采用双重循环进行排序,只不过是在内部的实现过程有些许差异罢了。
一言不合就贴代码:
public class LearnFastChoiseSort {
public static void main(String[] args) {
LearnFastChoiseSort lfcs = new LearnFastChoiseSort();
lfcs.sort();
}
void sort() {
int array[] = new int[]{98, 3, 5, 45, 15 ,46 ,1, 2, 49};
//int max = array[0];
int temp;
int index;
for (int i = 1; i < array.length; i++) {
index = 0;
for (int j = 1; j <= array.length-i; j++) {
if (array[index] > array[j]) {
index = j;
}
temp = array[array.length - i];
array[array.length - i] = array[index];
array[index] = temp;
}
}
for (int i = 0; i < array.length; i++) {
System.out.print(array[i]+" ");
}
}
}
- 反转排序:
顾名思义,反转排序是将数组中的元素由原来的顺序反过来排序。
基本原理:将数组中的最后一个元素与第一个元素进行替换,将倒数第二个元素和第二个元素进行替换......知道把所有的数组元素替换完毕。
感觉这种排序实现起来还蛮容易的,拿代码测试下:
public class LearnReversalSort {
public static void main(String[] args) {
int array[] = new int[]{98, 3, 5, 45, 15 ,46 ,1, 2, 49};
int temp;
for (int i = 1; i < array.length*0.5+1; i++) {
for (int j = i-1; j < i; j++) {
temp = array[j];
array[j] = array[array.length-i];
array[array.length-i] = temp;
}
}
for (int i : array) {
System.out.print(i+" ");
}
}
}
因为每次排序只交换两个元素,即:只进行一次排序。且在第一轮是交换第一个与最后一个元素,第二趟是交换第二个和倒数第二个元素...以此类推。所以在内层for循环中采用int j = i-1; j < i; j++的条件。
posted on 2016-07-18 20:57 Rocking7189 阅读(537) 评论(0) 收藏 举报
浙公网安备 33010602011771号