【Java基础】(七)数组

一、什么是数组

数组是存储同一数据类型多个元素的集合。
1)既可以存放基本数据类型元素,也可以存放引用数据类型元素(比如String就是一种引用数据类型)
2)数组本身是引用数据类型
3)初始化之后长度不可改变

二、为什么要有数组

假如我们要做一个用来签到的小程序,假设有三个学生,把他们的签到情况设置成boolean类型,如果他们来签到了,那么设为true,否则为false。那我们要怎么做呢,那我们要建立三个boolean类型的变量,然后分别操作。如下:

package com.daw.test1;

import java.util.Scanner;

public class Test2 {
	
	public static void main(String[] args) {
		
		//定义三个学生的签到情况
		boolean stu0 = false;
		boolean stu1 = false;
		boolean stu2 = false;
		
		Scanner scanner = new Scanner(System.in);
		int id = -1;	//id表示当前签到学生的编号
		
		while(true){
			
			System.out.print("系统闲置,请输入签到编码:");
			id = scanner.nextInt();
			
			//判断编码属于哪个学生,并签到
			if(id == 0){
				stu0 = true;
			}else if (id == 1) {
				stu1 = true;
			}else if (id == 2) {
				stu2 = true;
			}else {
				//注意,一个好的程序应当尽量应对到所有可能
				System.out.println("无效的编码,请重新输入!");
				continue;
			}
			System.out.println("签到成功!");
			
			if((stu0==true) && (stu1==true) && (stu2==true)){
				//所有学生都签到完成后,跳出程序
				System.out.println("全勤!");
				break;
			}
		}
	}
	
}

虽然是个错误示范,但希望没什么基础的同学也敲一敲,也当复习上次内容了。
可见,整个程序很长,而且很多操作都是重复的。况且每个学生的签到情况都有自己的名字,管理起来也及其不方便。这个人就得写这么多,如果一个班五十多人,甚至一百人,公司一千人,以这样的方式,程序员不累死也得烦死。
本着不迫害程序员的态度,数组就诞生了。上面的程序,如果用数组来实现,将会是这样的:

package com.daw.test1;

import java.util.Scanner;

public class Test2 {
	
	public static void main(String[] args) {
		
		//定义10个学生的签到情况
		boolean[] stu = new boolean[10];	//此处并没有给它们赋值,但它们却是各个都有值的,详情下面讲
		
		Scanner scanner = new Scanner(System.in);
		int id = -1;	//id表示当前签到学生的编号
		
		while(true){
			
			System.out.print("系统闲置,请输入签到编码:");
			id = scanner.nextInt();
			
			//判断编码属于哪个学生,并签到
			if((id>=0) && (id<=10)){
				stu[id] = true;
			}else {
				//注意,一个好的程序应当尽量应对到所有可能
				System.out.println("无效的编码,请重新输入!");
				continue;
			}
			System.out.println("签到成功!");
			
			//用于标记是否所有人都已经签到
			boolean flag = false;
			for(int i = 0; i < 10; i++){
				if (stu[i] == false) {
					flag = false;
					break;
				}
				//所有人都签到了
				flag = true;
			}
			
			if (flag == true) {
				System.out.println("全勤");
				break;
			}
		}
	}
	
}

看上去好像和上面长度差不多,但实际上这个稍微改改数字,就可以完成一千人,一万人的签到。而上面的则需要不断地重复写相似的内容,人数越多,代码越多。

三、数组的定义

两种方式:
数据类型[] 数组名;
数据类型 数组名[];
例:

int[] nums;
int nums[];

四、数组的初始化

1)静态初始化—初始化时指定每个数组元素的初始值,由系统决定数组长度

	int[] arr = new int[]{1, 2, 3};
	int[] arr = {1, 2, 3};

2)动态初始化—初始化时只指定数组长度,由系统为数组分配初始值

	int[] arr = new int[5];

3)数组的长度—数组名.length

如arr.length

4)访问数组中的元素

	数组名[下标]
	下标的范围 0~数组的长度-1

我们编码试一试,敲一段,运行看看结果,然后注释掉已经运行完的部分,再往下敲。不要一次性敲完,不然输出一堆,懒得看结果。

package com.daw.test;

public class Test01 {

	public static void main(String[] args) {
		//静态初始化一个数组
		//int[] arr = new int[]{1,2,3};
		int[] arr = {188,255,3646};
		//打印数组长度
		System.out.println(arr.length);
		//打印数组中元素
		System.out.println(arr[0]);
		System.out.println(arr[1]);
		System.out.println(arr[2]);
		
		System.out.println("----------------");
		
		//动态初始化一个数组 ---- 探究基本数据类型(8)的初始值
		//整数
		byte[] arrByte = new byte[3];
		int[] arrInt = new int[3];   
		short[] arrShort = new short[3];
		long[] arrLong = new long[3];
		System.out.println(arrByte[0]);
		System.out.println(arrInt[0]);
		System.out.println(arrShort[0]);
		System.out.println(arrLong[0]);
		System.out.println("----------------");
		
		//小数
		double[] arrDouble = new double[3];
		float[] arrFloat = new float[3];
		System.out.println(arrDouble[0]);
		System.out.println(arrFloat[0]);
		System.out.println("----------------");
		
		//布尔
		boolean[] arrBoolean = new boolean[3];
		System.out.println(arrBoolean[0]);
		System.out.println("----------------");
		
		//字符
		char[] arrChar = new char[3];
		System.out.println(arrChar[0]);
		System.out.println(arrChar[0] + 0);
		/*
		 * 基本数据类型的初始值为 0
		 * */
		
		//探究引用型数据类型(自定义)的初始值
		String[] arrString = new String[10];
		System.out.println(arrString[9]);
		System.out.println("----------------");
		Student[] arrStudent = new Student[3];
		System.out.println(arrStudent[0]);
		System.out.println("----------------");
		/*
		 * 引用数据类型的初始值为null
		 * */
	}

}

总结:动态初始化时,系统为每个元素指定初始值

	基本数据类型
		|-byte	0
		|-short	0
		|-int	0
		|-long	0
		|-double 0.0
		|-float	 0.0
		|-boolean false
		|-char 	0
	引用数据类型----null
		|-String null

五、常见问题

1)ArrayIndexOutOfBoundsException–下标越界异常

出现此错误说明你在访问数组时,超出了数组的范围。

package com.daw.test;

public class Test02 {

	public static void main(String[] args) {
		int[] arr = new int[10];
		//ArrayIndexOutOfBoundsException --- 数组下标越界异常,操作的位置超出数组长度
		System.out.println(arr[10]);
	}

}

2)NullPointerException–空指针异常

不止在数组中出现,此错误说明,你使用的对象并未初始化 或 指向null。

package com.daw.test;

public class Test02 {

	public static void main(String[] args) {
		int[] arr = new int[10];
		//NullPointerException --- 空指针异常,操作的指针为空
		arr = null;
		System.out.println(arr.length);
	}

}

六、数组常见操作

1)遍历

可有三种方式实现:

package com.daw.test;

public class Test03 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] arr = {100, 99, 101, 200, 1};
		//for循环
		for(int index = 0; index < arr.length; index++){
			System.out.println(arr[index]);
		}
		System.out.println("**********");
		
		//while循环
		int index = 0;
		while(index < arr.length){
			System.out.println(arr[index]);
			index++;
		}
		System.out.println("**********");
		
		//增强for循环 --- foreach --- 可以遍历一切多项的变量
		for(int item : arr){ //每次遍历都将arr中的一项赋值到item中
			System.out.println(item);
		}
		System.out.println("**********");
	}

}

2)求最值

package com.daw.test;
public class Test04 {

	public static void main(String[] args) {
		int[] arr = {5, 4, 1000, -9999999, 6};
		//最大值
		int max = arr[0];
		for(int i : arr){
			if(max < i){
				max = i;
			}
		}
		System.out.println(max);
		//最小值
		int min = arr[0];
		for(int i : arr){
			if(min > i){
				min = i;
			}
		}
		System.out.println(min);
	}

}

3)逆序

package com.daw.test;

public class Test05 {

	public static void main(String[] args) {
		int[] arr = {1, 4, 9, 3, 2};
		for(int i = 0, j = arr.length - 1; i < j; i++, j--){	//for循环,初始化语句有多条时,用","分割,而不是";"
			//变量交换
			int temp = arr[i];
			arr[i] = arr[j];
			arr[j] = temp;
		}
		for(int i = 0; i < arr.length; i++){
			System.out.println(arr[i]);			
		}
		
	}

}

4)选择排序

	|---选定一个元素和其后的元素进行比较
	|---每一轮比较完成都会选出最大或最小的元素

5)冒泡排序

	|---相邻元素两两进行比较
	|---如果数组已经排好序,如何减少比较次数

数据结构中较为简单的算法,根据要求自己尝试编写。

七、数组一旦初始化,长度不可改变

涉及计算机基础知识,初学者知道这一性质即可。
在计算机内存中,有系统栈和系统堆两块儿区域,我们所声明的变量的名和值会放置在系统栈的一块区域中,但栈中每块区域的大小是特定的。而数组等引用类型的数据大小可能会特别的大,而且长度也并不像基本数据类型那样确定。但为了在进行调用的时候所有的对象的操作保持一致,因此在系统栈中,引用数据类型的“值”实际上是一块地址,其真正的值存贮在对应的地址上的堆中。当一个数组初始化时,就会在堆内开辟确定长度的一块儿区域。
比如我们打印一下我们初识化过得数组:

System.out.println(arr);

会发现打印出来一堆乱七八糟的有数字有符号,有字母。其实那表示一个地址。
而试图改变数组长度,就像盖房子一样,去申报得到了一块儿地,但是你盖着盖着发现你想要把房子盖的更大,但是你周围的地政府可能已经给别人了,或者有其他的目的和打算,你多盖一些,他多盖一些,就把整个政府的计划给搞乱了。为了避免这种情况,如果你盖着盖着,发现地不够了,那你可以去重新申请一片更大的地,这片地就归还国家了。
图示,假设我定义如下;

int i = 5;
float f =1.63;
int[] arr = new int[4];

那他们在系统栈和堆上是这样的。
在这里插入图片描述
假如,我们觉得arr不够用,于是我们又申请了另一个长度为5的数组

arr = new int[7];

在这里插入图片描述
可以看出,当你更换了区域以后,原来的数据并不会改变,只不过它不再属于你了而已。这就像前女…

总结:
	栈:
		基本数据类型变量存值
		引用数据类型变量存址
	堆:
		对象,数组---通过new生成的区域

八、二维数组&多维数组

在实际开发中使用很少。二维数组,本质就是以一维数组为元素的一维数组。三维数组也一样,就是以二维数组为元素的一维数组,多维数组同理。
所以啊,它就是个一维数组,你知道了它的定义方式,拿着以为数组的初始化套着玩玩就行了。
定义也很简单:

//二维数组
int[][] arr = new int[5][];
//三维数组
int[][][] arr1 = new int[5][][];

想要几维数组,就几个括号,至于括号在变量名前后,都可,甚至可以几个在前几个在后。这也表明了,多维数组的实质就是一维数组,只不过我们之前学的一维数组的元素都不是数组而已。所以多维数组也可以使用所有一维数组的操作。
需要注意的是,定义多维数组时,只必需给出最前面的长度。为啥?因为它就是个一维数组啊,它里面的元素是数组,就是一种引用数据类型,默认值就是null呗,所以里面的元素你想在一开始赋值就赋值,不想赋值就算了。
它就是一个一维数组。
至于二维数组和多维数组的遍历,相信学过嵌套循环的你已经不会被这种垃圾问题难住了,不多讨论,告辞。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值