六、《数组》的作用以及使用场景

前言

        在之前我们可以通过一个变量表示一个学生的年龄,如果现在需要表示全班 100 个人的年龄岂不是需 要定义 100 个变量来分别表示。这样的操作变量的命名容易冲突,并且也会导致代码量大,可读性差等问题。那么怎么解决这种问题呢?Java 就提供了数组解决这种问题。

1、数组概念

概念:计算机在内存区域分配的一段连续的区域,用来存储同种类型的数据。

简单的理解,数组就是一堆盒子,同一时间,可以保存多个相同数据类型的数据。

  • 数组名  :数组的名字。
  • 数组元素:就是存放在数组里面的数据。
  • 数组索引:就是数组里面连续存储空间的编号,从0开始。
  • length  :数组的属性长度,数组名.length拿到数组的长度。

数组作用:可以解决同时保存多个数据的问题。 

2、数组声明

回忆定义变量的语法: 数据类型 变量; 如 int age;

数组的声明语法:

数据类型[] 数组名; 【目前只是单纯声明,还不能使用】

如:

int[] ages; // 表示声明一个int类型数组ages,这个数组只能装int类型元素

String[] names; // 表示声明一个String类型数组names,这个数组只能装String类型元素

另一种方式:int ages[];【不推荐】。

3、数组赋值

数组在定义后,必须初始化【赋值】才能使用。所谓初始化,就是在堆内存中给数组分配存储空间,并为每一个元素赋上初始值,有两种方式:

3.1、动态创建

语法:数据类型[] 数组名 = new 数据类型[长度];// 长度不能为负数,且是int类型 最大就是int最大值。

// 数组声明: 动态创建,语法 :数据类型[] 数组名 = new 数据类型[长度];
//长度不能为负数,且是int类型 最大就是int最大值
int[] arr = new int[3]; // 动态创建了一个int类型的数组arr,长度3

3.2、静态创建

语法:数据类型[] 数组名 = {值1, 值2, 值3.....};// 最常用

语法:数据类型[] 数组名 = new 数据类型[]{值1,值2,值3.....};// 不常用。了解

//  数组声明:静态创建,语法 :数据类型[] 数组名 = {元素1, 元素2, 元素3....};
int[] arr2 = {6, 9, 69}; // 静态创建了一个int类型的数组arr,赋值元素 :6, 9, 69

怎么选择用动态创建还是静态创建?

根据实际情况确定,知道具体的数据,用静态创建,不知道用动态创建。

3.3、数组赋值

语法:数组名[下标] = 值;

// 2 数组赋值:语法,数组名[下标] = 值;
arr[0] = 1; // 给数组arr第1个元素赋值1
arr[1] = 2; // 给数组arr第2个元素赋值2
arr[2] = 3; // 给数组arr第3个元素赋值3

4、数组取值

语法:数组名[下标];

取值后,主要用于:

  1. 直接打印输出
  2. 赋值给另外一个变量
  3. 直接计算
  4. 作为方法参数使用
    // 数组取值:语法,数组名[下标];  直接打印元素即可
    System.out.println("第1个元素 : " + arr[0]); // 直接打印第1个元素
    System.out.println("第2个元素 : " + arr[1]); // 直接打印第2个元素
    System.out.println("第3个元素 : " + arr[2]); // 直接打印第3个元素

5、数组遍历

遍历:就是将数组中每一个元素取出来。

5.1、for + index【普通for循环】

根据上面取值的代码,可以发现一个规律,下标都是从0开始,到length-1结束。因此我们通过循环可以得到下标,而得到下标后,进而可以通过下标获取对应元素:

数组遍历【将所有元素取出来就是遍历】
// 先打印数组arr所有下标
for (int i = 0; i < arr.length; i++) { // i表示下标,循环次数就是到 最后一个下标arr.length - 1
// 打印下标:i
System.out.println("下标:" + i);
// 打印元素:arr[i]【通过下标获取对应元素】
System.out.println("元素==== :" + arr[i]);
}

5.2、增强for循环

语法:

for(元素类型 e : 数组/集合){

        ​e是变量,随便命名。就是每次获取到的元素

}

/*
*  数组遍历第二种方式:增强for循环 foreach
*  
  *  方式2: 简化遍历数组的过程
*    2. 增强for循环: foreach
		语法:
for(元素数据类型 变量名 : 数组名){
	 变量名 //就是每一次获取到的元素
}
*/
for (int e : arr) { // arr是数组名, int 是元素类型  e变量是每一个元素
    System.out.println("元素 :" + e);
}

5.3、数组的内存图

/**
*	数组内存分析图【理解】
* 基本类型具体的值在栈帧中	
* 引用类型具体的值在堆中
*/

public static void main(String[] args) {
	int[] arr2 = {1, 2, 5};
	int[] arr = new int[3];
	System.out.println(arr[0]);
	System.out.println(arr[1]);
	System.out.println(arr[2]);
	System.out.println(arr);
	arr[0] = 1;
	arr[1] = 9;
	arr[2] = 6;
//	arr[3] = 5; // ArrayIndexOutOfBoundsException 数组下标越界异常。证明下标超过了数组有效范围
		
	int a = 1;
	int b = 1;
	a = 2;	
}

5.4、分析图:

 6、数组注意事项

1、数组的下标范围是[0,arr.length-1],使用数组的时候,超过下标范围会报错

ArrayIndexOutOfBoundsException 数组下标越界异常。

例如:数组长度是3个,但是现在操作第4个元素arr[3]就会报这个错误。

2、数组动态创建可以分为两步:

2.1、int[] arr; //只是声明一个int类型的数组,还没有创建(即,还没有分配内存空间)

2.2、arr = new int[长度]; //分配内存空间,动态创建数组

3、数组静态创建可以分为两步:

3.1、int[] arr; //只是声明一个int类型的数组,还没有创建(即,还没有分配内存空间)

3.2、arr = new int[]{1,2,43}; // 分配内存空间,动态创建数组

不能直接这样写:arr = {1,2,43}; // 语法错误

4、数组一旦创建,长度就固定不变了。

如果长度不够或者长度多了,就需要创建新数组,将原来数组中元素复制到新数组中。int[] arr = {1,2,43};

arr = new int[]{1,43}; //开辟新的内存区域,重新创建新的数组扩容、缩容

5、数组是引用数据类型,直接打印数组名是打印的地址

6、动态创建,没有给数组元素赋值,则系统会分配默认值

(byte/short/int/long)整数类型默认值:0

(float、double)小数类型默认值:0.0

boolean类型:false

char类型默认值:空字符

7、空指针异常:NullPointerException,操作了一个尚未初始化或者没有分配内存空间的数组,即,没有只是声明,但是没有创建的数组。

8、数组声明可以这样,但是不建议

int arr[] = new int[2];// []在数组名后,不建议

6.1、部分测试代码:

public class _06Array {
/** static修饰int[]类型成员变量newArr,声明不赋值 */
static int[] newArr;	
public static void main(String[] args) {
	// 静态创建分2步
	int[] arr2;
	// 创建
	arr2 = new int[]{1, 2, 5};		
	// 动态创建分2步
	int[] arr;
	arr = new int[2];	
	// 使用成员变量newArr
	System.out.println(newArr); // null
	// 使用成员变量newArr.length
	System.out.println(newArr.length); // NullPointerException空指针异常
	
	int arr3[] = new int[2]; // 不建议	
}
}

7、数组联系题【建议初学者学习】

public static void main(String[] args) {
		// 需求 1:找出数组nums中元素 22 第一次出现的索引位置
		int[] nums = {11, 22, 33, 44, 22, 55};
		/*
		 * 分析:普通for循环【因为用下标】,遍历数组nums,将每一个元素跟22比较,如果相等,就打印下标,结束break循环
		 */
		// 普通for循环【因为用下标】,遍历数组nums
		for (int i = 0; i < nums.length; i++) {
			// if判断,将每一个元素nums[i]跟22比较,如果相等
			if (nums[i] == 22) {
				// 如果相等,就打印下标
				System.out.println("下标:" + i);
				// 结束break循环
				break;
			}
		}
		
		// 需求 2:求出数组nums2中所有元素的和
		int[] nums2 = {11, 22, 33, 44, 22, 55};
		// 遍历全部不用下标,用foreach循环
		// 声明一个int变量sum装和,赋值0
		int sum = 0;
		for (int e : nums2) {
			// 将每一个元素e累加到sum中
			sum += e;
		}
		System.out.println("和:" + sum);
		
		// 需求 3:求出数组nums3中所有偶数元素、奇数元素的和
		int[] nums3 = {11, 22, 33, 44, 22, 55};
		int evenSum = 0; // 声明一个int变量evenSum装偶数和,赋值0
		int oddSum = 0; // 声明一个int变量oddSum装奇数和,赋值0
		// 遍历全部不用下标,用foreach循环
		for (int e : nums3) {
			// 判断当前元素e是否是偶数,如果是累加到evenSum中,如果不是则累加到oddSum
			if (e % 2 == 0) { // 判断e是否是偶数
				evenSum += e;
			} else {
				oddSum += e;
			}
		}
		System.out.println("偶数和:" + evenSum + "  奇数和:" + oddSum);

	}

		int[] nums = {11, 22, 33, 44, 22, 55};
		System.out.println(nums); // 打印的是地址,没有意义
		/*
		 * 需求 4:希望将该数组进行字符串拼接,这样我们就你可以打印字符串的指定格式: [元素1, 元素2, 元素3....]
		 * 思路:要遍历数组,将数组元素进行字符串拼接
		 * 	步骤:
		 * 		1. 声明一个String类型str,赋值为"[",用来拼接字符串的
		 * 		2. 遍历数组nums,初始化条件,从下标0开始,循环结束条件到倒数第二个元素
		 * 			每次循环,都将获取到的元素nums[i]拼接到str中,然后在继续拼接一个逗号
		 * 		3. 循环结束后,再将最后一个元素nums[nums.length - 1]拼接上,拼接 结尾]
		 */
		// 1. 声明一个String类型str,赋值为"[",用来拼接字符串的
		String str = "[";
		// 2. 遍历数组nums,初始化条件,从下标0开始,循环结束条件到倒数第二个元素
		for (int i = 0; i <= nums.length - 2; i++) {
			// 每次循环,都将获取到的元素nums[i]拼接到str中
			str += nums[i] + ", ";
		}
		System.out.println(str);
		// 3. 循环结束后,再将最后一个元素nums[nums.length - 1]拼接上,拼接 结尾]
		str += nums[nums.length - 1] + "]";
		System.out.println("拼接后: " + str);
		
		// 需求5:求出数组arr中的最大值
		int[] arr = {11, 22, 33, 44, 22, 55};
		/*
		 * 思路:
		 * 	将第一个和第二个比较大小,找出最大的,保存到临时变量中,然后继续跟下一个比较,一直比较到最后一个元素,循环结束后,最大的值就找到了
		 */
		int max = arr[0];// 声明一个临时变量max,赋值arr第一个元素,保存的都是遍历到的最大值
		// 普通for循环,下标从1开始
		for (int i = 1; i < arr.length; i++) { // 下标从1开始,到最后一个元素结束
			// 将当前遍历到的元素arr[i]跟临时变量max比较,如果当前元素arr[i]>max,就给max重新赋值
			if (arr[i] > max) {
				max = arr[i]; //就给max重新赋值为当前元素arr[i]
			}
		}
		System.out.println("最大值:" + max);
		
		// 需求6:求出数组arr中的最大和最小值
		int max2 = arr[0]; // 声明一个临时变量max2,赋值arr第一个元素,保存的都是遍历到的最大值
		int min = arr[0]; // 声明一个临时变量min,赋值arr第一个元素,保存的都是遍历到的最小值
		// 普通for循环,下标从1开始
		for (int i = 1; i < arr.length; i++) { // 下标从1开始,到最后一个元素结束
			// 将当前遍历到的元素arr[i]跟临时变量max2比较,如果当前元素arr[i]>max2,就给max2重新赋值
			if (arr[i] > max2) {
				max2 = arr[i]; //就给max2重新赋值为当前元素arr[i]
			}
			// 将当前遍历到的元素arr[i]跟临时变量min比较,如果当前元素arr[i]<min,就给min重新赋值
			if (arr[i] < min) {
				min = arr[i]; //就给min重新赋值为当前元素arr[i]
			}
		}
		System.out.println("======最大值:" + max2);
		System.out.println("======最小值:" + min);
		
		
		// 需求7:请将"我" "爱" "你" 存入数组,然后正着和反着输出
		String[] iLoveYou = {"我", "爱", "你"};
		// 正序输出
		for (String s : iLoveYou) {
			System.out.println(s);
		}
		// 反着输出
		for (int i = iLoveYou.length - 1; i >= 0; i--) {
			System.out.println(iLoveYou[i]);
		}

8、本章重点

数组声明、赋值、取值、遍历

for循环执行流程

9、数组加强练习

数组在实际工作及很多底层都有使用到,因此做一个加强练习。

完成以下关于数组相关练习题

1. 统计一个字符在字符数组中第一次出现的下标(直接输出)

2. 统计一个字符在字符数组中出现的次数(直接输出)

3. 已知这样的整型数组 int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22}; 计算出其中的奇数和以及偶数和

4. 现在有数组 double[] scores = {11, 34, 76, 77, 88, 99, 58, 97, 56};统计并打印出每一个阶段的学生人数(分段方式:0-60; 60-80;80-100)

5.翻转传入数组中的元素

例如有这样的数组 char[] arr = {'贤', '叔', '同', '学'};

调用完上面的方法之后,arr中的内容是这样的{'学', '同', '叔', '贤'};

下一章《方法》的引入和作用以及使用。


版权声明:本文为yqx1714768514原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。