在某些情况下,虽然可以使用单个变量来存储信息,但是如果需要存储的信息较多(例如存储 50 名学生的成绩),这时再依次创建变量声明并赋值显得非常麻烦。
随着处理的信息量越来越大,工作也就越来越烦琐,这时可以使用数组或集合来存储信息。通过使用数组,可以在很大程度上缩短和简化程序代码,从而提高应用程序的效率。
数组(array)是一种最简单的复合数据类型,它是有序数据的集合,数组中的每个元素具有相同的数据类型,可以用一个统一的数组名和不同的下标来确定数组中唯一的元素。根据数组的维度,可以将其分为一维数组、二维数组和多维数组等。
在计算机语言中数组是非常重要的集合类型,大部分计算机语言中数组具有如下三个基本特性:
一致性:数组只能保存相同数据类型元素,元素的数据类型可以是任何相同的数据类型。
有序性:数组中的元素是有序的,通过下标访问。
不可变性:数组一旦初始化,则长度(数组中元素的个数)不可变。
总的来说,数组具有以下特点:
数组可以是一维数组、二维数组或多维数组。
数值数组元素的默认值为 0,而引用元素的默认值为 null。
数组的索引从 0 开始,如果数组有 n 个元素,那么数组的索引是从 0 到(n-1)。
数组元素可以是任何类型,包括数组类型。
数组类型是从抽象基类 Array 派生的引用类型。
注意:如果你熟悉 C/C++,请注意,Java 数组的工作原理与它们不同。
在 Java 中数组的下标是从零开始的,很多计算机语言的数组下标也从零开始。Java 数组下标访问运算符是中括号,如 intArray[0],表示访问 intArray 数组的第一个元素,0 是第一个元素的下标。Java 中的数组本身是引用数据类型,它的长度属性是 length。
type [ ] arrayName;// 数据类型[ ] 数组名;
arrayName = new type [ size ];// 数组名 = new 数据类型 [ 数组长度 ];
使用 new 指定数组大小后进行初始化
type [ ] arrayName = new int [ size ] ;
如果程序员只指定了数组的长度,那么系统将负责为这些数组元素分配初始值。指定初始值时,系统按如下规则分配初始值。
数组元素的类型是基本类型中的整数类型(byte、short、int 和 long),则数组元素的值是 0。
数组元素的类型是基本类型中的浮点类型(float、double),则数组元素的值是 0.0。
数组元素的类型是基本类型中的字符类型(char),则数组元素的值是‘\u0000’。
数组元素的类型是基本类型中的布尔类型(boolean),则数组元素的值是 false。
数组元素的类型是引用类型(类、接口和数组),则数组元素的值是 null。
arrayName[index];其中,arrayName 表示数组变量,index 表示下标,下标为 0 表示获取第一个元素,下标为 array.length-1 表示获取最后一个元素。当指定的下标值超出数组的总长度时,会拋出 Array异常。
int[] number = {1,2,3,5,8};
System.out.println("获取第一个元素:"+number[0]);
System.out.println("获取最后一个元素:"+number[number.length-1]);
System.out.println("获取第6个元素:"+number[5]);
import java.util.Scanner; public class Test { public static void main(String[] args) { int[] prices = new int[5]; Scanner input = new Scanner(System.in); for (int i = 0; i < prices.length; i++) { System.out.println("请输入第" + (i + 1) + "件商品的价格:"); prices[i] = input.nextInt(); } System.out.println("第 3 件商品的价格为:" + prices[2]); } }
在 Java 中二维数组被看作数组的数组,即二维数组为一个特殊的一维数组,其每个元素又是一个一维数组。Java 并不直接支持二维数组,但是允许定义数组元素是一维数组的一维数组,以达到同样的效果。
type arrayName[][]; // 数据类型 数组名[][];
int[][] age; char[][] sex;
type[][] arrayName = new type[][]{值 1,值 2,值 3,…,值 n}; // 在定义时初始化 type[][] arrayName = new type[size1][size2]; // 给定空间,在赋值 type[][] arrayName = new type[size][]; // 数组第二维长度为空,可变化 有如上3种方式
int[][] temp = new int[][]{{1,2},{3,4}};
public class Test11 { public static void main(String[] args) { // 创建一个二维矩阵 int[][] matrix = new int[5][5]; // 随机分配值 for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[i].length; j++) { matrix[i][j] = (int) (Math.random() * 10); } } System.out.println("下面是程序生成的矩阵\n"); // 遍历二维矩阵并输出 for (int k = 0; k < matrix.length; k++) { for (int g = 0; g < matrix[k].length; g++) { System.out.print(matrix[k][g] + ""); } System.out.println(); } } }
public static void main(String[] args) { double[][] class_score = { { 100, 99, 99 }, { 100, 98, 97 }, { 100, 100, 99.5 }, { 99.5, 99, 98.5 } }; for (double[] row : class_score) { for (double value : row) { System.out.println(value); } } }
Java 的数组要求所有的数组元素具有相同的数据类型。因此,在一个数组中,数组元素的类型是唯一的,即一个数组里只能存储一种数据类型的数据,而不能存储多种数据类型的数据。
因为 Java 语言是面向对象的语言,而类与类之间可以支持继承关系(从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为),这样可能产生一个数组里可以存放多种数据类型的假象。例如有一个水果数组,要求每个数组元素都是水果,实际上数组元素既可以是苹果,也可以是香蕉(苹果、香蕉都继承了水果,都是一种特殊的水果),但这个数组的数组元素的类型还是唯一的,只能是水果类型。
一旦数组的初始化完成,数组在内存中所占的空间将被固定下来,因此数组的长度将不可改变。即使把某个数组元素的数据清空,但它所占的空间依然被保留,依然属于该数组,数组的长度依然不变。
Java 的数组既可以存储基本类型的数据,也可以存储引用类型的数据,只要所有的数组元素具有相同的类型即可。
值得指出的是,数组也是一种数据类型,它本身是一种引用类型。例如 int 是一个基本类型,但 int[](这是定义数组的一种方式)就是一种引用类型了。
int[] 是一种类型吗?怎么使用这种类型呢?
没错,int[] 就是一种数据类型,与 int 类型、String 类型相似,一样可以使用该类型来定义变量,也可以使用该类型进行类型转换等。使用 int[] 类型来定义变量、进行类型转换时与使用其他普通类型没有任何区别。int[] 类型是一种引用类型,创建 int[] 类型的对象也就是创建数组,需要使用创建数组的语法。
Arrays.fill(array,value);
import java.util.Arrays; public class Main { private static int i; public static void main(String[] args) { // write your code here int arr[] = new int[5]; Arrays.fill(arr,8); for (int i = 0; i < arr.length; i++); System.out.println( +arr[i]); }}
public static void main(String[] args) { int[] number = new int[5]; System.out.println("number —共有 " + number.length + " 个元素,它们分别是:"); for (int i = 0; i < number.length; i++) { Arrays.fill(number, i); System.out.println("number[" + i + "]=" + i); } }
在 Java 中实现数组复制分别有以下 4 种方法:
Arrays 类的 copyOf() 方法
Arrays 类的 copyOfRange() 方法
System 类的 arraycopy() 方法
Object 类的 clone() 方法
使用 copyOf() 方法和 copyOfRange() 方法
srcArray 表示要进行复制的数组,length 表示复制后的新数组的长度。
使用这种方法复制数组时,默认从原数组的第一个元素(索引值为 0)开始复制,目标数组的长度将为 length。如果 length 大于 srcArray.length,则目标数组中采用默认值填充;如果 length 小于 srcArray.length,则复制到第 length 个元素(索引值为 length-1)即止。
注意:目标数组如果已经存在,将会被重构。
import java.util.Arrays; public class Test19{ public static void main(String[] args) { // 定义长度为 5 的数组 int scores[] = new int[]{57,81,68,75,91}; // 输出原数组 System.out.println("原数组内容如下:"); // 循环遍历原数组 for(int i=0;i<scores.length;i++) { // 将数组元素输出 System.out.print(scores[i]+"\t"); } // 定义一个新的数组,将 scores 数组中的 5 个元素复制过来 // 同时留 3 个内存空间供以后开发使用 int[] newScores = (int[])Arrays.copyOf(scores,8); System.out.println("\n复制的新数组内容如下:"); // 循环遍历复制后的新数组 for(int j=0;j<newScores.length;j++) { // 将新数组的元素输出 System.out.print(newScores[j]+"\t"); } } }
使用 CopyOfRange() 方法对数组进行复制
srcArray 表示原数组。
startIndex 表示开始复制的起始索引,目标数组中将包含起始索引对应的元素,另外,startIndex 必须在 0 到 srcArray.length 之间。
endIndex 表示终止索引,目标数组中将不包含终止索引对应的元素,endIndex 必须大于等于 startIndex,可以大于 srcArray.length,如果大于 srcArray.length,则目标数组中使用默认值填充。
注意:目标数组如果已经存在,将会被重构。
public class Test20 { public static void main(String[] args) { // 定义长度为8的数组 int scores[] = new int[] { 57, 81, 68, 75, 91, 66, 75, 84 }; System.out.println("原数组内容如下:"); // 循环遍历原数组 for (int i = 0; i < scores.length; i++) { System.out.print(scores[i] + "\t"); } // 复制原数组的前5个元素到newScores数组中 int newScores[] = (int[]) Arrays.copyOfRange(scores, 0, 5); System.out.println("\n复制的新数组内容如下:"); // 循环遍历目标数组,即复制后的新数组 for (int j = 0; j < newScores.length; j++) { System.out.print(newScores[j] + "\t"); } } }
使用 arraycopy() 方法
srcArray 表示原数组;srcIndex 表示原数组中的起始索引;destArray 表示目标数组;destIndex 表示目标数组中的起始索引;length 表示要复制的数组长度。
使用此方法复制数组时,length+srcIndex 必须小于等于 srcArray.length,同时 length+destIndex 必须小于等于 destArray.length。
注意:目标数组必须已经存在,且不会被重构,相当于替换目标数组中的部分元素。
public class Test21 { public static void main(String[] args) { // 定义原数组,长度为8 int scores[] = new int[] { 100, 81, 68, 75, 91, 66, 75, 100 }; // 定义目标数组 int newScores[] = new int[] { 80, 82, 71, 92, 68, 71, 87, 88, 81, 79, 90, 77 }; System.out.println("原数组中的内容如下:"); // 遍历原数组 for (int i = 0; i < scores.length; i++) { System.out.print(scores[i] + "\t"); } System.out.println("\n目标数组中的内容如下:"); // 遍历目标数组 for (int j = 0; j < newScores.length; j++) { System.out.print(newScores[j] + "\t"); } System.arraycopy(scores, 0, newScores, 2, 8); // 复制原数组中的一部分到目标数组中 System.out.println("\n替换元素后的目标数组内容如下:"); // 循环遍历替换后的数组 for (int k = 0; k < newScores.length; k++) { System.out.print(newScores[k] + "\t"); } } }
clone() 方法也可以实现复制数组。该方法是类 Object 中的方法,可以创建一个有单独内存空间的对象。因为数组也是一个 Object 类,因此也可以使用数组对象的 clone() 方法来复制数组。
public class Test22 { public static void main(String[] args) { // 定义原数组,长度为8 int scores[] = new int[] { 100, 81, 68, 75, 91, 66, 75, 100 }; System.out.println("原数组中的内容如下:"); // 遍历原数组 for (int i = 0; i < scores.length; i++) { System.out.print(scores[i] + "\t"); } // 复制数组,将Object类型强制转换为int[]类型 int newScores[] = (int[]) scores.clone(); System.out.println("\n目标数组内容如下:"); // 循环遍历目标数组 for (int k = 0; k < newScores.length; k++) { System.out.print(newScores[k] + "\t"); } } }
冒泡排序(Bubble Sort)是常用的数组排序算法之一,它以简洁的思想与实现方法而备受青睐,也是广大学习者最先接触的一种排序算法。
冒泡排序的基本思想是:对比相邻的元素值,如果满足条件就交换元素值,把较小的元素值移动到数组前面,把大的元素值移动到数组后面(也就是交换两个元素的位置),这样数组元素就像气泡一样从底部上升到顶部。
冒泡排序的算法比较简单,排序的结果稳定,但时间效率不太高。Java 中的冒泡排序在双层循环中实现,其中外层循环控制排序轮数,总循环次数为要排序数组的长度减 1。而内层循环主要用于对比相邻元素的大小,以确定是否交换位置,对比和交换次数依排序轮数而减少。
ublic static void main(String[] args) { System.out.println("通过冒泡排序方法对数组进行排序:"); for (int i = 0; i < score.length - 1; i++) { // 比较相邻两个元素,较大的数往后冒泡 for (int j = 0; j < score.length - 1 - i; j++) { if (score[j] > score[j + 1]) { double temp = score[j + 1]; // 把第一个元素值保存到临时变量中 score[j + 1] = score[j]; // 把第二个元素值转移到第一个元素变量中 score[j] = temp; // 把临时变量(第一个元素的原值)保存到第二个元素中 } System.out.print(score[j] + " "); // 对排序后的数组元素进行输出 } System.out.print("【"); for (int j = score.length - 1 - i; j < score.length; j++) { System.out.print(score[j] + " "); } System.out.println("】"); } }
import java.util.Arrays; import java.util.Scanner; public class yu {public static void main(String[] args){ int xLen = 3; int yLen = 3; int[][] a = new int[xLen][yLen]; //使用随机数填充二维数组 for(int i=0;i<xLen;i++) { for(int j=0;j<yLen;j++) { a[i][j] = (int)(Math.random() * 100); } } //复制二维数组到一维数组 int[] b = new int[xLen * yLen]; int k = 0; for(int i=0;i<xLen;i++) { for(int j=0;j<yLen;j++) { b[k++] = a[i][j]; } } System.out.println("排序前:"); for(int i=0;i<xLen;i++) { System.out.println(Arrays.toString(a[i])); } //调用Arrays中的sort方法 Arrays.sort(b); //将排序后的值复制回二维数组 k = 0; for(int i=0;i<xLen;i++) { for(int j=0;j<yLen;j++) { a[i][j] = b[k++]; } } System.out.println("排序后:"); for(int i=0;i<xLen;i++) { System.out.println(Arrays.toString(a[i])); } }
使用选择排序法也可以对上述数组中的元素进行排序,但是它与冒泡排序不同。选择排序是指每一趟从待排序的数据元素中选出最大(或最小)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。
int[] number = {13,15,24,99,4,1}; String end = "\n"; int index; for (int i = 1;i < number.length;i++) { index = 0; for(int j = 1;j <= number.length-i;j++) { if (number[j] > number[index]) { index = j; // 查找最大值 } } end = number[index] + " " + end; // 定位已排好的数组元素 int temp = number[number.length-i]; number[number.length-1] = number[index]; number[index] = temp; System.out.print("【"); for (int j = 0;j < number.length-i;j++) { System.out.print(number[j]+" "); } System.out.print("】"+end); }
Array,Sort(object)//object类
public static void main(String[] args) { // 定义含有5个元素的数组 double[] scores = new double[] { 78, 45, 85, 97, 87 }; System.out.println("排序前数组内容如下:"); // 对scores数组进行循环遍历 for (int i = 0; i < scores.length; i++) { System.out.print(scores[i] + "\t"); } System.out.println("\n排序后的数组内容如下:"); // 对数组进行排序 Arrays.sort(scores); // 遍历排序后的数组 for (int j = 0; j < scores.length; j++) { System.out.print(scores[j] + "\t"); } }
利用 Collections.reverseOrder() 方法//包装类
public static void main(String[] args) { Integer[] a = { 9, 8, 7, 2, 3, 4, 1, 0, 6, 5 }; // 数组类型为Integer Arrays.sort(a, Collections.reverseOrder()); for (int arr : a) { System.out.print(arr + " "); } }
实现 Comparator 接口的复写 compare() 方法
public class Test { public static void main(String[] args) { /* * 注意,要想改变默认的排列顺序,不能使用基本类型(int,double,char)而要使用它们对应的类 */ Integer[] a = { 9, 8, 7, 2, 3, 4, 1, 0, 6, 5 }; // 定义一个自定义类MyComparator的对象 Comparator cmp = new MyComparator(); Arrays.sort(a, cmp); for (int arr : a) { System.out.print(arr + " "); } } } // 实现Comparator接口 class MyComparator implements Comparator<Integer> { @Override public int compare(Integer o1, Integer o2) { /* * 如果o1小于o2,我们就返回正值,如果o1大于o2我们就返回负值, 这样颠倒一下,就可以实现降序排序了,反之即可自定义升序排序了 */ return o2 - o1; } }