第四章 数组

4.1 数组的概述

数组是具有相同数据类型的一组数据的集合,例如,球类的集合--足球、篮球、羽毛球等;器集合--电视机、洗衣机、电风扇等。在程序设计中,可以将这些集合称为数组。数组中的每个元素具有相同的数据类型。在 Java 中同样将数看作是一个对象,虽然基本数据类型不是对象由基本数据类型组成的数组则是对象。在程序设计中引入数组可以更有效地管理和处理数据。我们经常使用的数组包括一维数组和二维数组等。

4.2 一堆数组

一维数组​​​​​​​时至上是一组相同类型数据的线性集合,例如学校中学生们排列的一字长队就是一个数组,每一位学生都是数组中的一个元素。再比如快捷酒店,就相当于一个一维数组,每一个房间
都是这个数组中的元素。当在程序中需要处理一组数据, 或者传递一组数据时,就可以使用数组实现。本节将介绍一维数组的创建及使用。

4.2.1 创建一堆数组

数组元素类型决定了数组的数据类型,它可以是Java中任意的数据类型,包括基本数据类型和其他引用类型。数组名字为一个合法的标识符,符号“[ ]”指明该变量是一个数组类型变量。单“[ ]”表示要创建的数组是一个一维数组。
声明一维数组有两种方式:  

数组元素类型   数组名字[];  

数组元素类型[]    数组名字;

声明一维数组,语法如下:


int arr[];       //声明int型数组,数组中的每个元素都是int型数值 
double[] dou;       //声明 double 型数组,数组中的每个元素都是 double 型数值

声明数组后,还不能访问它的任何元素,因为声明数组只是给出了数组名字和元素的数据类型要想真正使用数组,还要为它分配内存空间。在为数组分配内存空间时必须指明数组的长度。为数组分配内存空间的语法格式如下:


数组名字=new数组元素类型[数组元素的个数];

数组名字:被连接到数组变量的名称。
数组元素个数:指定数组中变量的个数,即数组的长度。为数组分配内存,语法如下:


arr=new int[5]; //数组长度为 5 


以上代码表示要创建一个有5个元素的整型数组,并且将创建的数组对象赋给引用变量anr,即引用变量arr引用这个数组,
上面代码中arr为数组名称,括号“[ ]”中的值为数组的下标,也叫索引。数组通过下标来区分不同的元素,也就是说,数组中的元素都可以通过下标来访问。这就相当于刚才比喻的快捷酒店,我们想要找到某个房间里的人,只需要知道这个人所在房间号。这个房间号就相当于数组的下标。
数组的下标是从0开始的。由于创建的数组arr中有5个元素,因此数组中元素的下标为 0~4在声明数组的同时也可以为数组分配内存空间,这种创建数组的方法是将数组的声明和内存的分配合在一起执行,语法如下:
数组元素类型数组名=new数组元素类型[数组元素的个数];                                                             声明并为数组分配内存,语法如下: int month[] = new int[12];
上面的代码创建数组month,并指定了数组长度为12。这种创建数组的方法也是Java程序编写过程中普遍的做法。

4.2.2 初始化一维数组

数组可以与基本数据类型一样进行初始化操作,也就是赋初值。数组的初始化可分别初始化组中的每个元素。数组的初始化有以下3种方式:

int a[ ]={1,2,3};

int b[ ]= new int[ ]{4,5,6};

int c[ ] = new int[3];

c[0] = 7;

c[1] = 8;

c[2] = 9;

从中可以看出,数组的初始化就是包括在大括号之内用逗号分开的表达式列表。用逗号“”分隔数组中的各个元素,系统自动为数组分配一定的空间。第一种初始化方式,将创建3个元素的数组,依次为 1、2、3:第二种初始化方式,创建3个元素的数组,依次为 4、5、6:第三种初始化方式先给数组创建了内存空间,再给数组元素逐一赋值。

4.2.3 获取数组长度

我们初始化一维数组的时候都会在内存中分配内存空间,内存空间的大小决定了一维数组能够储存多少个元素,也就是数组长度该如何获取数组长度呢?我们可以使用数组对象自带的 length属性。语法如下:

arr.length
 an :数组名。
length :数组长度属性,返回 int 值。

 例4.1

 
public class jay {//创建类
	public static void main(String[] args) {//主函数
		char a[] = { 'A', 'B', 'c', 'D' }; // 创建一维数组 
		System.out.println("数组a的长度为"+a.length); //输出数组a的长度
		char b[] =a; //创建一维数组b,直接等于数组a
		System.out.println("数组b的长度为"+b.length); //输出数组b的长度
	}
}

4.2.4 使用一维数组

在Java中,一维数组是最常见的一种数据结构。下面的实例是使用一维数组将1~12月份各月份的天数输出。

例4.2

public class jay {//创建类
 
	public static void main(String[] args) {//主函数
		int day[] = new int[] { 31,28,31,30,31,30,31,31,30,31,30,31}; // 创建一维数组 
		   for (int i = 0; i <12; i++) {//利用循环将信息输出
		       System.out.println((i+1)+"月有"+day[i]+"天");//输出的信
		   }
	}
 
}

4.3 二维数组

比如快捷酒店,每一个楼层都有很多房间,这些房间都可以构成一维数组,如果这个酒店有500
个房间,并且所有房间都在同一个楼层里,那么拿到499号房钥匙的旅客可能就不高兴了,从1号   
房走到499号房要花好长时间,因此每个酒店都不只有一个楼层,而是很多楼层,每一个楼层都会有很多房间,形成一个立体的结构,把大量的房间均摊了下来,这种结构就是二维表结构,如图4.7所示,在计算机中,这种二维表结构可以使用二维数组来表示。如图 4.7所示,每一个楼层都是一个一维数组,楼层数本身又构成了一个数组,这样一家酒店就构成了一个二维数组。                   二维数组常用于表示表,表中的信息以行和列的形式表示,第一个下标代表元素所在的行,第二个下标代表元素所在的列。

4.3.1 创建二维数组

二维数组可以看作是特殊的一维数组,因此,二维数组有两种声明方式:


数组元素类型数组名字[][];                        

数组元素类型[][]数组名字;    

声明二维数组,代码如下:

int tdarrl[][];        

char[][] tdarr2;


同一维数组一样,二维数组在声明时也没有分配内存空间,同样要使用关键字new 来分配内存,然后才可以访问每个元素。
为二维数组分配内存有两种方式:

int a[][];
a = new int[2][4]; //直接分配行列 
int b[][];
b=new int[2][]; //先分配行,不分配列

b[0]=new int[2];//给第一行分配列

b[1]=new int[2];//给第二行分配列

4.3.2 初始化二维数组

二维数组的初始化方法和一维数组类似也有三种方式,但不同的是二维数组有两个索引。

例4.3

public class jay {//创建类
 
	public static void main(String[] args) {//主函数
		   /*第一种方式*/
		   int tdarr1[][] = { { 1, 3, 5 },{ 5, 9, 10 } };// 创建二维数组 
		   /*二种方式*/
		   int tdarr2[][] = { { 65, 55, 12 },{ 92, 7, 22 } };// 创建二维数组 
		   /*第三种方式*/
		   int tdarr3[][] = new int[2][3]; // 先给数组分配内存空间
		   tdarr3[0] = new int [] {6, 54, 71};//给第一行分配一个一维数组
		   tdarr3[1][0] = 63; //给第二行第一列赋值为63
		   tdarr3[1][1] = 10;//给第二行第二列赋值为10
		   tdarr3[1][2] = 17;//给第二行第三列赋值为7
	}
 
}

4.3.3 使用二维数组

二维数组在实际应用中非常广泛。

例4.4

 
public class jay {//创建类
 
	public static void main(String[] args) {//主函数
		char arr[][] = new char[4][]; // 创建一个4行的二维数组
		  arr[0] = new char[] { '春','眠','不','觉','晓'}; // 赋值为'春','眠','不','觉','晓'
		  arr[1] =new char[] { '处','处','闻','啼','鸟'}; //赋值为 '处','处','闻','啼','鸟'
		  arr[2] = new char[] { '夜','来','风','语','声'}; //赋值为 '夜','来','风','语','声'
		  arr[3] = new char[] { '花','落','知','多','少' };//赋值为 '花','落','知','多','少'
		  /*横版输出*/
		  System.out.println("---横版---");//输出---横版---
		  for (int i = 0; i < 4; i++) {// 循环4行
		   for( int j=0;j < 5;j++){//循环5列
		  System.out.print(arr[i][j]);//输出数组中的素
		 }
		  if (i % 2 == 0) {//取余
		   System.out.println(",");//如果是一、三句,输出号
		   }else {
		    System.out.println("。");//如果是二、四句,输出句号
		 }
		  }
		  /*竖版输出*/
		  System.out.println("\n-----竖版-----"); //输出-----竖版-----
		  for (int j = 0; j < 5; j++) {// 列变行
		   for (int i = 3; i >=0; i--) {// 行变列,反序输出
		    System.out.print(arr[i][j]);//输出数组中的元素
		 }
		   System.out.println();//换行
		  }
		  System.out.println("。,。,");//输出最后的标点
	}
 
}

例4.5

public class jay {//创建类
	
	public static void main(String[] args) {//主函数
		// TODO Auto-generated method stub
	  char arr[][] = new char[4][]; // 创建一个4行的二维数组
	    arr[0] = new char[] { '春','眠','不','觉','晓'}; // 为每一行赋值 
	    arr[1] =new char[] { '处','处','闻','啼','鸟'}; //输出第二行
	    arr[2] = new char[] { '夜','来','风','语','声'}; //输出第三行
	    arr[3] = new char[] { '花','落','知','多','少' };输出第四行
	    /*横版输出*/
	    System.out.println("---横版---");//换行
	    for (int i = 0; i < 4; i++) {// 循环4行
	     for( int j=0;j < 5;j++){//循环5列
	    System.out.print(arr[i][j]);//输出数组中的素
	   }
	    if (i % 2 == 0) {//判断语句
	     System.out.println(",");//如果是一、三句,输出号
	     }else {
	      System.out.println("。");//如果是二、四句,输出句号
	   }
	    }
	    /*竖版输出*/
	    System.out.println("\n-----竖版-----"); //换行
	    for (int j = 0; j < 5; j++) {// 列变行
	     for (int i = 3; i >=0; i--) {// 行变列,反序输出
	      System.out.print(arr[i][j]);//输出数组中的元素
	   }
	     System.out.println();//换行
	    }
	    System.out.println("。,。,");//输出最后的标点
	 }
	
	}

4.4 数组的基本操作

1.往数组中添加一个元素:
push方法(在尾部添加)unshift方法(在头部添加)
二者均返回数组长度

2.从数组中删除一个元素:
pop() 方法(在尾部删除)shift() 方法(在头部删除)
二者均返回删除元素
总结:push()、pop()、shift()、unshift()都会改变原数组

 3.

提取数组中的一部分
slice() 方法:slice(开始位置,结束位置)
若只有一个参数,即无结束位置参数,则从开始到结束
若结束位置大于开始位置,则返回空数组

其中计算时不包括结束位置,不改变原素组,返回提取的新数组
当位置上的数字为正时:

当位置上的数字小于0时:

最后,原数组不改变

4.删除数组中的一部分元素
最终操作的结果会改变原数组
splice()方法:splice(开始位置,删除个数)返回删除的元素
splice(开始位置,删除个数,插入元素)
负数表示从倒数开始计算

 5.reverse()
将数组中的元素逆转放置,操作改变原数组

6.sort()
sort() 方法用于对数组的元素进行排序。
请注意,下面的代码没有按照数值的大小对数字进行排序,而是按照字典进行排序
操作会改变原数组

7.join()
join() 方法用于把数组中的所有元素放入一个字符串。
元素是通过指定的分隔符进行分隔的。
若括号里什么都不写,则默认用逗号分隔
若是引号,则空白分隔

4.4.1遍历数组

遍历数组就是获取数组中的每个元素,通常遍历数组都是使用for循环来实现的,遍历一维数组很简单,也很好理解,遍历二维数组需使用双层for循环,通过数组的Length属性可获得数组的长度。

例4.6

public class jay {//创建类
 
	public static void main(String[] args) {//主函数
		int b[][] = new int[][] { { 1 }, { 2, 3 }, { 4, 5, 6 } }; // 定义二维数组 
		for (int k = 0; k < b.length; k++) {//循环遍历二维数组中的每个元素
		   for (int c = 0;c < b[k].length;c++){ //循环遍历二维数组中的每个元素
		       System.out.print(b[k][c]); //将数组中的元素输出
		   }
		   System.out.println();//输出换行
		   }
	}
 
}

4.4.2 填充和批量替换数组元素

数组中的元素定义完成后,可通过 Arrays类的静态方法 fill0来对数组中的元素进行分配,可以起到填充和替换的效果。fill()方法有两种参数类型,下面以 int型数组为例介绍 fill()方法的使用。
1. fill(intl a , int value)
该方法可将指定的int值分配给int型数组的每个元素。语法如下:


Arrays.fill(int[] a, int value)

a:要进行元素分配的数组。
value:要存储数组中所有元素的值

例4.7

import java.util.Arrays;//导入输出函数需要用到的包
public class jay {//创建类
 
	public static void main(String[] args) {//主函数
		 int arr[] = new int[5];//创建int型数组
		 Arrays.fill(arr, 8); // 使用同一个值对数组进行填充
		 for (int i = 0; i < arr.length; i++) {// 循环遍历数组中的元素
		  //将数组中元素依次输出
		     System.out.println("第"+i+"个元素是:"+arr[i]);//输出"第"+i+"个元素是:"+arr[i]
 
		  }
	}
 
}

2. fill(int]a, int fromindex, int tolndex, int value)
该方法将指定的 int 值分配给int型数组指定范围中的每个元素。填充的范围从索引 fromIndex(包括)一直到索引toIndex(不包括)。如果fromIndex==toIndex,则填充范围为空。语法如下:


Arrays.fill(int[] a,int fromIndex, int toIndex, int value)

a:要进行分配的数组。
yfromIndex:要使用指定值填充的第一个元素的索引(包括)。                                                      toIndex:要使用指定值填充的最后一个元素的索引(不包括)。                                                            value:要存储在数组所有元素中的值。                                                                                                注意:如果指定的索引位置大于或等于要进行分配的数组的长度,则会报出 ArrayIndexOutOf-BoundsException(越界异常)异常。

例4.8

import java.util.Arrays;//导入输出函数需要用到的包
public class jay {//创建类
 
	public static void main(String[] args) {//主函数
		int arr[] = new int[] { 45, 12, 2, 77, 31, 91, 10 };// 定义并初始化 int 型数组arr
		  Arrays.fill(arr,1, 4,8); //使用fill()方法对数组进行填充 
		  for (int i = 0; i < arr.length; i++) {//循环遍历数组中的元素
		   //将数组中的元素输出
		  System.out.println("第" + i + "个元素是:" + arr[i]);//输出"第" + i + "个元素是:" + arr[i]
		  }
	}
 
}

4.4.3 复制数组

Arrarys 类的copyOf0方法与copyOfRange方法可实现对数组的复制。copyOf方法是复制数组   
至指定长度,copyOfRangeO方法则将指定数组的指定长度复制到一个新数组中。
1. copyOf()方法
该方法提供了多种使用方式,用于满足不同类型数组的复制。语法如下:

Arrays.copyof(arr,int newlength)

arr:要进行复制的数组。
ynewlength:int型常量,指复制后的新数组的长度。如果新数组的长度大于数组ar的长度,
则用0填充(根据复制数组的类型来决定填充的值,整型数组用0填充,char 型数组则使用null);果数长小数组arr,会从arr第一个元素开始截取至满足新数组长度为止。

例4.9

import java.util.Arrays;//导入输出函数需要用到的包
public class jay {//创建类
 
	public static void main(String[] args) {//主函数
		 int arr[] = new int[] { 23, 42, 12 };// 定义数组
		 int newarr[]=Arrays.copyOf(arr, 5); //复制数组arr
		 for (int i = 0; i < newarr.length; i++) {//循环变量复制后的新数组
		   System.out.println("第" + i + "个元素是:" + newarr[i]); //将新数组输出
		 }
	}
 
}

2、copyofRange()方法                                                                                                                该方法提供了多种使用方式,其常用语法如下:


Arrays.copyofRange(arr,int formIndexint toIndex)


arr:要进行复制的数组对象。 formIndex:指定开始复制数组的索引位置。formIndex必须在0至整个数组的长度之间。新
数组包括索引是formIndex的元素。
toIndex:要复制范围的最后索引位置。可大于数组arr的长度。新数组不包括索引是toIndex的元素。

例4.10

import java.util.Arrays;//导入输出函数需要用到的包
public class jay {//创建类
 
	public static void main(String[] args) {//主函数
		 int arr[] = new int[] { 23, 42, 12, 84, 10 }; // 定义数组
		 int newarr[] = Arrays.copyOfRange(arr, 0, 3); // 复制数组 
		 for (int i =0; i < newarr.length; i++){ //循环遍历复制后的新数组
		   System.out.println(newarr[i]);// 将新数组中的每个元素输出
		  }
	}
 
}

4.5 数组的排序

在程序设计中,经常需要将一组数据进行排序,这样更加方便统计与查询。程序常用的排序方法有冒泡排序、选择排序等。本节将对常用的数据排序方法进行详细讲解

4.5.1 算法:冒泡排序

冒泡排序是最常用的数组排序算法之一,它以简洁的思想与实现方法备受青睐,是初学者最先   
接触的一个排序算法。使用冒泡排序时,排序数组元素的过程总是小数往前放,大数往后放,类似水中气泡往上升的动作,所以称作冒泡排序。
1.基本思想
冒泡排序的基本思想是对比相邻的元素值,如果满足条件就交换元素值,把较小的元素移动到数组前面,把较大的元素移动到数组后面(也就是交换两个元素的位置),这样较小的元素就像气泡一样从底部上升到顶部。
2.计算过程
冒泡算法由双层循环实现,其中外层循环用于控制排序轮数,一般是要排序的数组长度减1次,因为最后一次循环只剩下一个数组元素,不需要对比,同时数组已经完成排序了。而内层循环主要用于对比数组中每个临近元素的大小,以确定是否交换位置,对比和交换次数以排序轮数而减少。例如,一个拥有6个元素的数组,在排序过程中每一次循环的排序过程和结果如图 4.18所示。
第一轮外层循环时把最大的元素值63移动到了最后面(相应的比63小的元素向前移动,类似气泡上升),第二轮外层循环不再对比最后一个元素值63,因为它已经确认为最大(不需要上升),应该放在最后,需要对比和移动的是其他剩余元素,这次将元素24移动到了63的前一个位置。其他循环将依此类推,继续完成排序任务。

例4.11

 
public class jay {//创建类
		/**
		  * 冒泡排序方法
		  * 
		  * @param array
		  *    要排序的数组
		  */
		 public void sort(int[] array) { //定义了一个方法传入了一个数组
		 for (int i = 1; i < array.length; i++) {//弄一个循环不要让比较的数超过数组的长度
		     for (int j = 0; j < array.length - i; j++){//比较相邻两个元素,较大的数往后冒泡
		       if(array[j] > array[j + 1]) {//如果前一个元素比后一个元素大,则两元素互换
		         int temp = array[j]; // 把第一个元素值保存到临时变量中
		         array[j] = array[j+1];//把第二个元素值保存到第一个元素单元中 
		         array[j + 1] =temp; // 把临时变量(也就是第一个元素原值)保存到第二个元素中
		    }
		   }
		  }
		  showArray(array);//输出冒泡排序后的数组元素
		 }
		 /**
		  * 显示数组中的所有元素
		  * 
		  * @param array
		  *    要显示的数组
		  */
		 public void showArray(int[] array) {//定义了一个方法传入了一个数组
		  System.out.println("冒泡排序的结果:"); //输出冒泡排序的结果
		  for (int i :array) { // 遍历数组
		   System.out.print(i + " ");//输出每个数组元素值
		  }
		  System.out.println();
		 }
		 public static void main(String[] args) {//主函数
		 int[] array={63, 4, 24, 1, 3, 15 }; //创建一个数组,这个数组元素是乱序的
		 Holle4_11 sorter=new Holle4_11();//创建排序类的对象
		 sorter.sort(array);//调用排序方法数组排序 
	}
 
}

4.5.2 算法:选择排序

直接选择排序方法属于选择排序的一种,它的排序速度要比冒泡排序快一些,也是常用的排序算法,是初学者应该掌握的。
1.基本思想
直接选择排序的基本思想是将指定排序位置与其他数组元素分别对比,如果满足条件就交换元素值,注意这里区别冒泡排序,不是交换相邻元素,而是把满足条件的元素与指定的排序位置交换(如从最后一个元素开始排序),这样排序好的位置逐渐扩大,最后整个数组都成为已排序好的格式。
这就好比有一个小学生,从包含数字1~10的乱序的数字堆中分别选择合适的数字,组成一个从1~10的排序,而这个学生首先从数字堆中选出1,放在第一位,然后选出2(注意这时数字堆中已经没有1了),放在第二位,依此类推,直到找到数字 9,放到8的后面,最后剩下 10,就不用选择了,直接放到最后就可以了。
与冒泡排序相比,直接选择排序的交换次数要少很多,所以速度会快些。
2. 计算过程
每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。

例4.12

 
public class jay {//创建类
		/**
		  * 直接选择排序法
		  *  @param array 
		  *    要排序的数组
		  */
		 public void sort(int[] array) {//定义了一个方法传入了一个数组
		 int index;//定义int类型的index
		     for (int i = 1; i <array.length; i++) {//使用for循环
		         index = 0;//将index赋值为0
		     for (int j = 1; j <= array.length - i; j++) {//使用for循环
		         if (array[j] > array[index]) {//使用if循环
		             index = j;//将index赋值为j
		    }
		   }
		   // 换在置array.length-i和index(最大值)上的两个数
		   int temp = array[array.length - i]; // 把第一个元素值保存到临时变量中
		   array[array.length - i] = array[index]; // 把第二个元素值保存到第一个元素单元中 
		   array[index] = temp; // 把临时变量也就是第一个元素原值保存到第二个元素中
		  }
		   showArray(array);//输出直接选择排序后的数组值 
		 }
		 /**
		  * 显示数组中的所有元素
		  *  @param array
		  *      要显示的数组
		  */
		 public void showArray(int[] array) {//定义了一个方法传入了一个数组
		  System.out.println("选择排序的结果为:"); 
		  for (int i : array) { //遍历数组
		   System.out.print(i + " ");//输出每个数组元素值
		  }
		  System.out.println();//换行
		 }
		 public static void main (String[] args) {//主函数
			 int[] array ={63, 4, 24, 1, 3, 15 };//创建排序类的对象
			 Holle4_11 sorter=new Holle4_11();//创建了新的对象
			 //调用排序方法数组排序 
			 sorter.sort(array);//输出sorter
		 }
}

4.5.3 Arrays.Sort()方法

通过Arrays类的静态sort()方法可实现对数组的排序。sort()方法提供了多种使用方式,可对任意类型数组进行升序排序。

语法如下:

Arrays.sort(object);

例4.13 

import java.util.Arrays;//导入输出函数需要用到的包
public class jay {//创建类
 
	public static void main(String[] args) {//主函数
		// TODO 自动生成的方法存根
		int arr[] = new int[] { 23, 42, 12, 8 }; // 声明数组
		Arrays.sort(arr); // 将数组进行排序
		System.out.println("排序后的结果为");//输出排序后的结果为
		for (int i = 0; i < arr.length; i++) { // 循环遍历排序后的数组
			System.out.print(arr[i]+" "); // 将排序后数组中的各个元素输出
		}
	}
 
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值