【Java基础】第3章_数组

本文详细介绍了Java中的数组概念、分类、一维数组和多维数组的使用,包括初始化、内存解析、元素访问、遍历及异常处理。此外,还涵盖了数组的默认初始化值、常见算法如查找、排序以及Arrays工具类的运用。通过对数组操作的深入理解,有助于提升编程能力。
摘要由CSDN通过智能技术生成

PPT链接:点击这里

1、 数组的概述

1、数组的理解

  • 数组(Array),是多个相同类型数据一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理

2、数组的相关概念

  • 数组名、元素、角标、下标、索引
  • 数组的长度:元素的个数

3、数组的特点

  • 数组本身是引用数据类型。数组中的元素既可以是基本数据类型也可以是引用数据类型
  • 创建数组对象会在内存中开辟一整块连续的空间,而数组名中引用的是这块连续空间的首地址
  • 数组的长度一旦确定,就不能修改
  • 数组是有序排列的

4、数组的分类

  • ① 按照维数:一维数组、二维数组、三维数组……

  • ② 按照数组元素类型:基本数据类型元素的数组、引用类型元素的数组

2、 一维数组的使用

数组元素的默认初始化值

  • 数组元素是整形:0
  • 数组元素是浮点型:0.0
  • 数组元素是char型:0'\u0000',而非'0'
  • 数组元素是boolean型:false
  • 数组元素是引用数据类型:null

数组是引用数据类型,赋值时用new,声明数组:int[] arr 可以将 int[] 看做数据类型更容易理解

public class ArrayTest {
	public static void main(String[] args) {
		
		int num;	//声明
		num = 10;	//初始化
		int id = 1001;	//声明 + 初始化
		
        //********************1.一维数组的声明和初始化**********
		int[] ids;	//声明
		//1.1 静态初始化:数组的初始化和数组元素的赋值操作同时进行
		ids = new int[]{1001,1002,1003,1004};	
		//1.2 动态初始化:数组的初始化和数组元素的赋值操作分开进行
		String[] names = new String[5]; 
		
		//也是正确的写法:
		int[] arr7 = {1,2,3,5,4};//类型推断
        
        //总结:数组一旦初始化完成,其长度就确定了
		
        //********************2.如何调用数组的指定位置的元素******
        //通过角标的方式调用,数组的角标(或索引)从0开始的,到数组的长度-1结束
		names[0] = "王铭";
		names[1] = "王赫";
		names[2] = "张学良";
		names[3] = "孙居龙";	
		names[4] = "王宏志"; //charAt(0)获取“王”
//		names[5] = "周扬"; //如果数组超过角标会通过编译,运行失败
        System.out.println(names[4].charAt(0));//王
		
        //********************3.如何获取数组的长度***************
		//属性:length
		System.out.println(names.length); //5
		System.out.println(ids.length); //4
		
        //********************4.如何遍历数组********************
		for(int i = 0;i < names.length;i++){
			System.out.println(names[i]);
		}
	}
}
public class ArrayTest {
	public static void main(String[] args) {
		//整形:0
		int[] arr = new int[4];
		for(int i = 0;i < arr.length;i++){
			System.out.println(arr[i]);
		}
		
		//浮点型:0.0	
		float[] arr2 = new float[5]; 
		for(int i = 0;i < arr2.length;i++){
			System.out.println(arr2[i]);
		}
		
		//字符型:0或'\u0000',而非'0'	
		char[] arr3 = new char[5]; 
		for(int i = 0;i < arr3.length;i++){
			System.out.println("----" + arr3[i] + "****");//---- ****
		}
		//验证
		if(arr3[0] == 0){
			System.out.println("你好!");
		}
		
		//布尔型:false	
		boolean[] arr4 = new boolean[5];
		for(int i = 0;i < arr2.length;i++){
			System.out.println(arr4[i]);
		}
		
		//引用数据类型:null 
		String[] arr5 = new String[5];
		for(int i = 0;i < arr2.length;i++){
			System.out.println(arr5[i]);
		}
		//验证
		if(arr5[0] == null){
			System.out.println("北京欢迎你!");
		}	
	}
}

2.1、内存的简化结构

2.2、一维数组的内存解析

【案例1】

int[] arr = new int[]{1,2,3};
String[] arr1 = new String[4];
arr1[1] = “刘德华”;
arr1[2] = “张学友”;
arr1 = new String[3];
System.out.println(arr1[1]);//null

【案例2】

image-20221108172119428

当堆中的数组没有栈中的变量指过来时(例如:方法执行完,变量全部出栈),这时就没有指针指向堆中new出来的空间,一段时间后该空间就会被当成垃圾回收

2.3、练习

从键盘读入学生成绩,找出最高分,并输出学生成绩等级
成绩>=最高分-10    等级为’A’
成绩>=最高分-20    等级为’B’
成绩>=最高分-30    等级为’C’
其余等级为’D’
提示:先读入学生人数,根据人数创建int数组,存放学生成绩

【代码实现】

import java.util.Scanner;
public class ArrayDemo {
	public static void main(String[] args) {
		//1.使用Scanner读取学生的个数
		Scanner scan = new Scanner(System.in);
		System.out.print("请输入学生人数:");
		int num = scan.nextInt();
		
		//2.创建数组,存储学生成绩,动态初始化
		int[] str = new int[num];
		System.out.println("请输入" + num + "个学生成绩");
				
		//3.给数组中的元素赋值
		int maxnum = 0;
		for(int i = 0;i < str.length;i++){
			str[i] = scan.nextInt();//直接输入数据给数组元素
			//4.获取数组元素中的最大值:最高分
			if(str[i] > maxnum){
				maxnum = str[i];
			}
		}
		
		//5.根据每个学生成绩与最高分的差值,得到每个学生的等级,并输出等级和成绩	
		char level;	//这里可以不用初始化,因为level一定会走 多选一 中的一个被赋值
		for(int i = 0;i < str.length;i++){
			if(maxnum - str[i] <= 10){
				level = 'A';
			}else if(maxnum - str[i] <= 20){
				level = 'B';
			}else if(maxnum - str[i] <= 30){
				level = 'C';
			}else{
				level = 'D';
			}
			System.out.println("student " + i + "score is" + str[i] + " grade is " + level);//不会报错,level会被赋值
		}
	}
}

3、 多维数组的使用

如果说可以把一维数组当成几何中的线性图形,那么二维数组就相当于是一个表格,像下图Excel中的表格一样

image-20220718123157664

对于二维数组的理解,我们可以看成是一维数组array1又作为另一个一维数组array2的元素而存在从数组底层的运行机制来看,其实没有多维数组

public class ArrayTest2 {
	public static void main(String[] args) {
        
		//********************1.二维数组的声明和初始化*************
		int[] arr = new int[]{1,2,3};//一维数组
		//静态初始化
		int[][] arr1 = new int[][]{{1,2,3},{4,5},{6,7,8}};
		//动态初始化1
		String[][] arr2 = new String[3][2];
		//动态初始化2
		String[][] arr3 = new String[3][];
		
		//也是正确的写法:
		int[] arr4[] = new int[][]{{1,2,3},{4,5,9,10},{6,7,8}};
		int[] arr5[] = {{1,2,3},{4,5},{6,7,8}};
		
		//********************2.如何调用数组的指定位置的元素********
		System.out.println(arr1[0][1]);//2
		System.out.println(arr2[1][1]);//null
//      System.out.println(arr3[1][0]);//会报错,出现空指针异常:java.lang.NullPointerException
        
		arr3[1] = new String[4];
		System.out.println(arr3[1][0]);//null
		
		//********************3.获取数组的长度********************
		System.out.println(arr4.length);//3
		System.out.println(arr4[0].length);//3
		System.out.println(arr4[1].length);//4
		
		//********************4.如何遍历二维数组******************
		for(int i = 0;i < arr4.length;i++){
			for(int j = 0;j < arr4[i].length;j++){
				System.out.print(arr4[i][j] + "  ");
			}
			System.out.println();
		}
	}
}

规定: 二维数组分为外层数组的元素,内层数组的元素

int[][] arr = new int[4][3];
外层元素:arr[0],arr[1]等------------行
内层元素:arr[0][0],arr[1][2]等------列

数组元素的默认初始化值

  • 针对于初始化方式1:比如:int[][] arr = new int[4][3];
    • 外层元素的初始化值为:地址值
    • 内层元素的初始化值为:与一维数组初始化情况相同
  • 针对于初始化方式2:比如:int[][] arr = new int[4][];
    • 外层元素的初始化值为:null
    • 内层元素的初始化值为:不能调用,否则报错
public class ArrayTest3 {
	public static void main(String[] args) {
		
		int[][] arr = new int[4][3];
		System.out.println(arr[0]);//[I@15db9742 
		System.out.println(arr[0][0]);//0
        
		System.out.println(arr);//[[I@6d06d69c
		
		float[][] arr1 = new float[4][3];
		System.out.println(arr1[0]);//地址值:[F@7852e922
		System.out.println(arr1[0][0]);//0.0
		
		String[][] arr2 = new String[4][2];
		System.out.println(arr2[1]);//地址值:[Ljava.lang.String;@4e25154f
		System.out.println(arr2[1][1]);//null
		
		double[][] arr3 = new double[4][];
		System.out.println(arr3[1]);//null
//		System.out.println(arr3[1][0]);//报错,出现空指针异常:java.lang.NullPointerException
	}
}

3.1、二维数组的内存解析

【案例1】

int[][] arr1 = new int[4][];
arr1[1] = new int[]{1,2,3};
arr1[2] = new int[4];
arr1[2][1] = 30;

【案例2】

int[][] arr4= new int[3][];
System.out.println(arr4[0]);//null
System.out.println(arr4[0][0]);//报错
arr4[0] = new int[3];
arr4[0][1] = 5;
arr4[1] = new int[]{1,2};

【案例3】

int[][] arr = new int[3][];
arr[1] = new int[]{1,2,3};
arr[2] = new int[3];
System.out.println(arr[0]);//null
System.out.println(arr[0][0]);//报异常

【案例4】

int[][] arr1 = new int[4][];
arr1[0] = new int[3];
arr1[1] = new int[]{1,2,3};
arr1[0][2] = 5;
arr1 = new int[2][];

3.2、练习

3.2.1、练习1

获取arr数组中所有元素的和。提示:使用for的嵌套循环即可

image-20221108174732240

【代码实现】

public class ArrayExer1 {
	public static void main(String[] args) {
		int[][] arr = new int[][]{{3,5,8},{12,9},{7,0,6,4}};
		
		int sum = 0;//记录总和
		for(int i = 0;i < arr.length;i++){
			for(int j = 0;j < arr[i].length;j++){
				sum += arr[i][j];
			}
		}
		System.out.println("总和为:" + sum);
	}
}

3.2.2、练习 2(判断)

3.2.3、练习 3(杨辉三角)

使用二维数组打印一个 10 行杨辉三角。
提示:
 1. 第一行有 1 个元素, 第 n 行有 n 个元素
 2. 每一行的第一个元素和最后一个元素都是 1
 3. 从第三行开始, 对于非第一个元素和最后一个元素的元素。即:
yangHui[i][j] = yangHui[i-1][j-1] + yangHui[i-1][j];

【代码实现】

public class YangHuiTest {
	public static void main(String[] args) {
		//1.声明并初始化二维数组
		int[][] yangHui = new int[10][];
		
		//2.给数组的元素赋值 注意:每一行有多少个元素
        //yangHui[0] = new int[1];
        //yangHui[1] = new int[2];
		for(int i = 0;i < yangHui.length;i++){
            //开辟空间,初试值是0
			yangHui[i] = new int[i + 1];
			//2.1 给首末元素赋值
			yangHui[i][0] = yangHui[i][i] = 1;
			//2.2 给每行的非首末元素赋值:忽略掉第1列和最后1列
			for(int j = 1;j < yangHui[i].length - 1;j++){//从第2列开始
				yangHui[i][j] = yangHui[i-1][j-1] + yangHui[i-1][j];
			}
		}
		
		//3.遍历二维数组
		for(int i = 0;i < yangHui.length;i++){
			for(int j = 0;j < yangHui[i].length;j++){
				System.out.print(yangHui[i][j] + "  ");
			}
			System.out.println();
		}
	}
}

3.2.4、练习 4(面试题目)

创建一个长度为 6 的 int 型数组,要求取值为 1-30,同时元素值各不相同

【代码实现1】

public class ArrayEver1 {
	public static void main(String[] args) {
        
		int[] arr = new int[6];
		for(int i = 0; i < arr.length; i++) {        
			arr[i] = (int)(Math.random() * 30) + 1;// [0,1) [0,30) [1,31)
		
			boolean flag = false;//flag:用于判断是否重复的标志
			while(true) {
				for(int j = 0; j < i; j++) {//比较 新来的数 和 前面已经赋值的数
					if(arr[j] == arr[i]) {
						flag = true;
						break;
					}
				}
				if(flag == true) {
					arr[i] = (int) (Math.random() * 30) + 1;//有重复就重新赋值
					flag = false;
					continue;//因为不能保证重新赋的值是否有重复,就重新启动for循环再判断是否重复
				}
				break;//均没有重复就结束while循环
			}
			
		}
		//遍历数组
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + " ");//25 29 27 14 30 2 
		}
	}
} 

【代码实现2】

public class ArrayEver2 {
	public static void main(String[] args) {
        
		int[] arr2 = new int[6];
		for (int i = 0; i < arr2.length; i++) {
			arr2[i] = (int) (Math.random() * 30) + 1;//[0,1) [0,30) [1,31)

			for (int j = 0; j < i; j++) {//比较 新来的数 和 前面已经赋值的数
				if (arr2[i] == arr2[j]) {
					i--; //i往前挪一位(因为最外层for循环会进行i++),让其重新赋值(下面的break会重新跳到最外层for循环)
					break; //结束内层的for循环
				}
			}
		}

		for (int i = 0; i < arr2.length; i++) {
			System.out.print(arr2[i] + " ");
		}
	}
} 

4、 数组中涉及到的常见算法

4.1、数组的最大值、最小值、平均数、总和

定义一个 int 型的一维数组,包含 10 个元素,分别赋一些随机整数,然后求出所有元素的最大值,最小值,总和值,平均值,并输出出来
要求:所有随机数都是两位数
public class ArrayTest1 {
	public static void main(String[] args) {
		int[] arr = new int[10];
		//数组赋值
		for(int i = 0;i <arr.length;i++){
			arr[i] = (int)(Math.random() * (99 - 10 + 1) + 10);//[10,99]
		}
		
		//遍历
		for(int i =0;i < arr.length;i++){
			System.out.print(arr[i] + " ");
		}
		System.out.println();
		
		//求数组元素的最大值
		int maxValue = arr[0];
		for(int i = 1;i < arr.length;i++){
			if(arr[i] > maxValue){
				maxValue = arr[i];
			}
		}
		System.out.println("最大值:" + maxValue);
		
		//求数组元素的最小值
		int minValue = arr[0];
		for(int i = 1;i <arr.length;i++){
			if(arr[i] < minValue){
				minValue = arr[i];
			}
		}
		System.out.println("最小值:" + minValue);
		
		//求数组元素的总和
		int sum = 0;
		for(int i = 1;i <arr.length;i++){
			sum += arr[i];
		}
		System.out.println("总和:" + sum);
		
		//求数组元素的平均数
		double avgVales = sum / arr.length;
		System.out.println("平均数:" + avgVales);		
	}
}

4.2、练习

(1)创建一个名为 ArrayTest 的类,在 main()方法中声明 array1 和 array2 两个变量,他们是 int[] 类型的数组
(2)使用大括号{},把 array1 初始化为 8 个素数:2,3,5,7,11,13,17,19。
(3)显示 array1 的内容。
(4)赋值 array2 变量等于 array1,修改 array2 中的偶索引元素,使其等于索引值(如 array[0]=0,array[2]=2)。打印出 array1。

【代码实现】

public class ArrayTest {
	public static void main(String[] args) {
		//1.声明 array1 和 array2 两个 int[]变量
		int[] array1,array2;
		//2.array1 初始化
		array1 = new int[]{2,3,5,7,11,13,17,19};
		
		//3.显示 array1 的内容
		for(int i = 0;i < array1.length;i++){
			System.out.print(array1[i] + "\t");
		}
		
		//4.1 赋值 array2 变量等于 array1 (不能称作数组的复制)
		array2 = array1;
		
		//4.2 修改 array2 中的偶索引元素,使其等于索引值(如 array[0]=0,array[2]=2)
		for(int i = 0;i < array2.length;i++){
			if(i % 2 == 0){
				array2[i] = i;
			}
		}
		System.out.println();
		
		//4.3 打印出 array1
		for(int i = 0;i < array1.length;i++){
			System.out.print(array1[i] + "\t");
		}
	}
}

思考:上述 array1 和 array2 是什么关系?

array1 和 array2 地址值相同,都指向了堆空间的唯一的一个数组实体

image-20220718230217566

拓展:修改题目,实现 array2 对 array1 数组的复制

image-20220718230915264

4.3、数组的复制、反转

public class ArrayTest2 {
	public static void main(String[] args) {
		String[] arr = new String[]{"JJ","DD","MM","BB","GG","AA"};
		
		//数组的复制(区别于数组变量的赋值:arr1 = arr)
		String[] arr1 = new String[arr.length];
		for(int i = 0;i < arr1.length;i++){
			arr1[i] = arr[i];
		}
		
		//数组的反转
		//方法1:
		for(int i = 0;i < arr.length / 2;i++){//注意:反转一半
			String temp = arr[i];
			arr[i] = arr[arr.length -1 - i];//理解:最后一个数的下标:length - 1
			arr[arr.length -1 -i] = temp;
		}
		
		//方法2:
		for(int i = 0,j = arr.length - 1; i < j; i++,j--){//第一个和最后一个
			String temp = arr[i];
			arr[i] = arr[j];
			arr[j] = temp;
		}
	}
}

4.4、数组中的查找(搜索)

4.4.1、线性查找

public class ArrayTest3 {
	public static void main(String[] args) {
		String[] arr = new String[]{"AA","BB","CC","DD","EE","FF"};
		
		String dest = "CC";//要查找的元素
		
		boolean isFlag = false;//没有找到时要有一个判断,否则找到和没找到都会输出Sout("很遗憾,没有找到的啦!");
		for(int i = 0;i < arr.length;i++){
			if(dest.equals(arr[i])){
				System.out.println("找到了指定的元素,位置为:" + i);
				isFlag = true;
				break;//如果找到就直接退出
			}
		}
		if(isFlag == false){
			System.out.println("很遗憾,没有找到的啦!");
		}
	}
}

引用数据类型比较两个数是否相等用equals(),equals 表示的是比较的内容相等,如:dest.equals(arr[i])比较 dest 和 arr[i] 的内容相等;如果是 int 类型进行比较则用dest == arr[i]

4.4.2、二分查找法

前提:所要查找的数组必须有序

注意: 循环条件要使用while(left <= right),因为当left == right时,区间[left,right]仍然有效

/*    2 5 7 8 10 15 18 20 22 25 28           20
      0 1 2 3  4  5  6  7  8  9 10
      low =  0  6  6  7
      hig = 10 10  7  7  在[7,7]范围内仍然要继续运行,接下来就是middle=7,找到20  */

public class ArrayTest4 {
	public static void main(String[] args) {
		int[] arr = new int[]{-98,-34,2,34,54,66,79,105,210,333};
		
		int dest = -34;
		int left = 0;//初始的首索引
		int right = arr.length - 1;//初始的末索引
        
		boolean isFlag = false;
		while(left <= right){//注意=
			int middle = (left + right) / 2;
			
			if(dest == arr[middle]){
				System.out.println("找到了指定元素,位置为:" + middle);
				isFlag = true;
				break;
			}else if(arr[middle] > dest){
				right = middle - 1;
			}else{	//arr[middle] < dest
				left = middle + 1;
			}	
		}
		
		if(isFlag == false){
			System.out.println("很遗憾,没找到!");
		}		
	}
}

4.5、冒泡排序

冒泡排序的原理非常简单,它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来

排序思想

  1. 比较相邻的元素。如果第一个比第二个大(升序),就交换他们两个
  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数
  3. 针对所有的元素重复以上的步骤,除了最后一个
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较为止

public class BubbleSortTest {
	public static void main(String[] args) {
		int[] arr = new int[]{43,32,76,92,-65,85,71,-42};
		
		for(int i = 0;i < arr.length - 1;i++){ //一共比较arr.length - 1轮,最后剩下最小的一个,不必比较
			for(int j = 0;j < arr.length - 1 - i;j++){ //每一轮比较几次
				if(arr[j] > arr[j+1]){ //j是从0开始的
					int temp = arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = temp;
				}
			}
		}
		//遍历
		for(int i = 0;i < arr.length;i++){
			System.out.print(arr[i] + "\t");
		}
	}
}

5、 Arrays 工具类的使用

java.util.Arrays 类即为操作数组的工具类,包含了用来操作数组(比如排序和搜索)的各种方法

工具类都是一些静态方法,可以通过类直接调用

import java.util.Arrays;

public class ArraysTest {
	public static void main(String[] args) {
		
		//1.boolean equals(int[] a,int[] b):判断两个数组是否相等
		int[] arr1 = new int[]{1,2,3,4};
		int[] arr2 = new int[]{1,3,2,4};
		boolean isEquals = Arrays.equals(arr1, arr2);
		System.out.println(isEquals);
		
		//2.String toString(int[] a):输出数组信息
		System.out.println(Arrays.toString(arr1));
		
			
		//3.void fill(int[] a,int val):将指定值填充到数组之中
		Arrays.fill(arr1,10);
		System.out.println(Arrays.toString(arr1));
		

		//4.void sort(int[] a):对数组进行排序
		Arrays.sort(arr2);
		System.out.println(Arrays.toString(arr2));
		
		//5.int binarySearch(int[] a,int key):对排序后的数组进行二分法检索指定的值
		int[] arr3 = new int[]{-98,-34,2,34,54,66,79,105,210,333};
		int index = Arrays.binarySearch(arr3, 210);
		if(index >= 0){
			System.out.println(index);
		}else{
			System.out.println("未找到");
		}
	}
}

6、 数组使用中的常见异常

1、数组角标越界的异常:ArrayIndexOutOfBoundsException

2、空指针异常:NullPointerException

public class ArrayExceptionTest {
	public static void main(String[] args) {
		
		//1.数组角标越界的异常:ArrayIndexOutOfBoundsException
		int[] arr = new int[]{1,2,3,4,5};
		//错误1:右越界
		for(int i = 0;i <= arr.length;i++){
			System.out.println(arr[i]);
		}
		//错误2:左越界
		System.out.println(arr[-2]);
		
		//2.空指针异常:NullPointerException
		//情况1:
		int[] arr2= new int[]{1,2,3};
		arr2 = null;
		System.out.println(arr2[0]);
		//情况2:
		int[][] arr2 = new int[4][];
		System.out.println(arr2[0][0]);
		//情况3:
        String[] arr3 = new String[]{"AA","BB","CC"};
		arr3[0] = null;
		System.out.println(arr3[0].toString());
	}
}

物竞天择,适者生存,加油吧 !!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值