本文仅作为个人笔记
数组
数组的引入
import java.util.Scanner;
public class TestArray01{
	public static void main(String[] args){
		//功能:键盘录入是个学生的成绩,求和,求平均数:
		//定义一个求和的变量:
		int sum = 0;
		Scanner sc = new Scanner(System.in);
		for(int i = 0; i<10;i++){//i:控制循环次数
			System.out.println("请录入第"+i+"个学生的成绩");
			int score = sc.nextInt();
			sum += score
		}
		System.out.println("是个学生的成绩之和为:"+sum);
		System.out.println("是个学生的成绩平均数为:"+sum/10);
		
		//这样写的缺点:
		//算出总成绩之后无法获得其中每个学生的成绩
	}
}
缺点:不能求每个学生的具体成绩是多少
解决:将成绩进行存储—》引入:数组
数组的作用:数组用来存储数据的,在程序设计中,为了处理方便,数组用来将相同类型的若干个数据组织起来,若干个数据的集合称为数组
数组的定义
静态初始化数组
定义数组的时候直接给数组赋值
静态初始化数组的格式
//完整格式
数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3...};
double[] score = new double[]{1.1,1.2,1.3,1.4};
int[] ages = new int[]{11,12,13};
//简化格式
数据类型[] 数组名 = {元素1,元素2,元素3,...};
int[] ages = {12,24,36}
数组的存储原理

 
-  数组的访问 数组名称[索引] System.out.println(scores[0]);//1.1 System.out.println(scores[2]);//1.3 scores[2] = 1.9;//数组的再赋值 System.out.println(scores[2]);//1.9数组的长度属性:length //长度属性:length //获取数组的长度(就是数组的个数) System.out.println(scores.length);//4数组的最大索引 数组的最大索引:数组名.length - 1 //前提:元素个数大于0
-  数组的注意事项 -  数据类型[] 数组名 也可以写成 数据类型 数组名[] int[] ages =...; int ages[] = ...; double[] scores = ...; double[] = scores = ...;
-  什么类型的数组存放什么类型的数据,否则报错 int[] arrs = new int[]{30,40,"黑马"};
-  数组一旦定义出来,程序执行的过程中,长度、类型就固定了。 
 
-  
public class ArrayAttentionDemo03 {
    public static void main(String[] args) {
        //目标:理解数组的注意事项
        //1、数据类型[] 数组名称 也可以写成 数据类型 数组名称[]
        int[] ages = {11,12,13};
        //int ages[] = {11,12,13};
        //2、什么类型的数组只能存放什么类型的元素
        // String[] names = {"小明","小王",22};//错误的
        //3、数组一旦定义出来之后,类型和长度就固定了
        int[] ages2 = {22,23,24};
        //System.out.println(ages2[3]);//报错,长度固定是三了不能访问第四个元素
    }
}
总结:
1.如何访问数组的元素
数组名称[索引]2.如何访问数组的长度
数组名称.length3.数组的最大索引怎么获取?
数组的最大索引:数组名.length - 1 //前提:元素个数大于0
public class ArrayDemo01 {
    public static void main(String[] args){
        //目标:学会使用静态初始化的方式定义数组
        //数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3...};
       // double[] scores = new double[]{1.1,1.2,1.3,1.4};
        double[] scores = {1.1,1.2,1.3,1.4};
       // int[] ages = new int[]{11,12,13};
        int[] ages ={11,12,13};
       // String[] names = new String[]{"小明","小红","小王"};
        String[] names = {"小明","小红","小王"};
        System.out.println("scores中存的是:"+scores);
        System.out.println(scores[0]);//1.1
        System.out.println(scores[2]);//1.3
        scores[2] = 1.9;
        System.out.println(scores[2]);//1.9
        //长度属性:length
        //获取数组的长度(就是数组的个数)
        System.out.println(scores.length);//4
    }
}
public class ArrayDemo02 {
    public static void main(String[] args) {
        //目标:学会访问数组的元素
        int [] ages = {11,12,13,14};
        //取值:数组名称[索引]
        System.out.println(ages[0]);
        System.out.println(ages[1]);
        System.out.println(ages[2]);
        System.out.println(ages[3]);
        //赋值:数组名称[索引] = 数据;
        ages[2] = 100;
        System.out.println(ages[2]);
        //访问数组的长度
        System.out.println(ages.length);//4
        //数组的最大索引:数组名.length - 1 //前提:元素个数大于0
    }
}
动态初始化数组
数组的动态初始化
- 定义数组的时候只确定元素的类型和数组的长度,之后再存入具体数据
数组的动态初始化格式:
数据类型[] 数组名 = new 数据类型[长度];
int[] arr = new int[3];
//后赋值
arr[0] = 10;
System.out.println(arr[0]);//10
总结
1.动态初始化的写法是什么样的?
数据类型[] 数组名 = new 数据类型[长度]; int[] arr = new int[4];2.两种数组定义时的特点和场景有什么区别
当前已经知道存入的元素值,用静态初始化。 当前还不清楚要存入哪些数据,用动态初始化
动态初始化数组的元素默认值
| 数据类型 | 明细 | 默认值 | 
|---|---|---|
| 基本类型 | byte、short、char、int、long | 0 | 
| 基本类型 | float、double | 0.0 | 
| 基本类型 | boolean | false | 
| 引用类型 | 类、接口、数组、String | null | 
两种初始化的使用场景总结、注意事项说明:
动态初始化:只 指定数据 长度,后期赋值 ,适合开始知道数据的数量,但是不确定具体元素值的业务场景。
静态初始化:开始就存入元素值,适合一开始就能确定元素值的业务场景。
两种格式的写法时严格独立的,不可以混用
int[] arrs = new int[3]{30,40,50}//这是错误的public class ArrayDemo05 { public static void main(String[] args) { //目标:掌握动态初始化元素默认值的规则。 //1、整形数组的元素默认值都是0 int[] arr = new int[10]; System.out.println(arr[0]);//0 System.out.println(arr[9]);//0 //2、字符数组的元素默认值都是0 char[] chars = new char[100]; System.out.println((int)chars[0]);//0 System.out.println((int)chars[99]);//0 //3、浮点型数组的元素默认值都是0.0 double[] scores = new double[90]; System.out.println(scores[0]);//0.0 System.out.println(scores[89]);//0.0 //4、布尔类型的数组 boolean[] booleans = new boolean[100]; System.out.println(booleans[0]);//false System.out.println(booleans[99]);//false //5、引用类型的数组 String[] names = new String[90]; System.out.println(names[0]);//null System.out.println(names[89]);//null } }
总结
1.动态初始化数组后元素的迷人之是什么样的?
- byte、short、int、long、char类型数组元素的默认值都是0
- float double 类型数组元素的默认值都是0.0
- boolean 类型数组元素的默认值是false、String类型数组元素的默认值是null
数组的遍历
- 遍历:就是一个一个数据的访问
- 遍历的作用:搜索、数据统计等等都需要用到遍历。
int[] ages = {20,30,40,50};
for(int i = 0; i <ages.length; i++){
    System.out.println(ages[i]);
}
public class ArrayDemo {
    public static void main(String[] args) {
        //目标:学会进行数组元素的遍历
        int[] arr ={12,24,36,48};
        //数组遍历形势
        //数组快捷方式:数组名.fori
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}
总结:
1.什么是遍历?
- 一个一个的把数据访问一遍
2.如何遍历数组?
int[] arr ={12,24,36,48}; for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); }
数组的案例
-  数组元素求和 需求:某部门5名员工的销售额分别是16、26、36、6、100,请计算出他们部门的总销售额。 public class Test01 { public static void main(String[] args) { //需求数组求和 int[] money ={16,26,36,6,100}; //定义总和 int sum = 0; //遍历数组中的每个元素 for (int i = 0; i < money.length; i++) { sum +=money[i]; } System.out.println("总金额为"+sum);//184 } }总结 1.如何实现批量数据的求和? -  使用数组存储批量数据 int[] money ={16,26,36,6,100};
-  遍历数组中的每个数据,然后定义变量把他们累加起来 //定义总和 int sum = 0; //遍历数组中的每个元素 for (int i = 0; i < money.length; i++) { sum +=money[i]; } System.out.println("总金额为"+sum);//184
 
-  
-  数组求最值 public class Test02 { public static void main(String[] args) { //需求:求数组元素最值。 //1.定义一个静态初始化的数组,存储一批数据 int[] data = {12,800,9000,20000,0,-5}; //2.定义一个变量用于存储最大值元素,建议使用第一个元素作为参照 int max = data[0]; //3.遍历数组的每个元素,依次与最大值变量的数据比较,若较大,则替换。 for (int i = 0; i < data.length; i++) { if(max<data[i]){ max = data[i]; } } //4.输出最大值变量存储的数据 System.out.println("最大值为"+max);//20000 } }总结: 1.数组元素求最大值如何实现的? - 数据拿到程序中去,用数组存储起来
- 定义一个变量用于记录最大值,这个变量建议默认存储第一个元素值作为参照。
- 遍历数组的元素,如果该元素大于变量存储的元素,则替换变量存储的值为该元素
 
-  猜数字游戏 需求:开发一个幸运小游戏,游戏规则如下: 游戏后台随机生成1-20之间的5个数(无所谓是否重复),然后让大家来猜数字 - 未猜中提示:“未命中”,并继续猜测
- 猜中提示:“运气不出,猜中了”,并输出该数据第一次出现的位置,且输出全部5个数据,最终结束本游戏。
 public class Test03 { public static void main(String[] args) { //需求:5个 1-20之间的是随机数,让用户猜测,猜中要提示猜中,还要输出该数据再数组中第一次出现的索引,并打印数组的内容出来。 //没有猜中接续。 //1、定义一个动态初始化数组存储5个随机的1-20之间的数据 int[] data = new int[5]; //2.动态的生成5个1-20之间的随机数并存入到数组中去。 for (int i = 0; i <data.length ; i++) { // data[i]= (int) (Math.random() * 20) + 1; } //3.使用一个死循环让用户进行猜测 Scanner sc = new Scanner(System.in); OUT: while (true){ System.out.println("请您输入一个1-20之间的整数进行猜测:"); int guessData= sc.nextInt(); //4.遍历数组中的每个数,看是否有数据与猜测的数据相同,相同代表猜中了,给出提示 for (int i = 0; i < data.length; i++) { if(data[i] == guessData){ System.out.println("您已经猜中了该数据,运气不错了!您猜中的数据索引是:" + i); break OUT;//结束了整个死循环代表游戏结束了! } } System.out.println("当前猜测的数据在数组中不存在,请重新猜测!"); } //5、输出数组的全部元素,让用户看到自己确实是猜中了某个数据。 for (int i = 0; i < data.length; i++) { System.out.print(data[i] + "\t"); } } }总结: 猜数字游戏的实现步骤? - 动态初始化数组,存入5个随机的1-20之间的数据
- 定义一个死循环,不断的才数据,遍历数组,判断数据是否再数组中,如果在,进行对应提示并结束死循环;如果没有猜中,提示继续
 
-  随机排名 需求:某公司开发部5名开发人员,要进行项目进展汇报演讲,现在采取随机排名后进行汇报。 请线依次录入5名员工的工号,然后展示出一组随机的排名顺序 22、33、35、13、88 -----》13、35、88、33、22 分析: - 在程序录入5名员工的工号存储起来 —》使用数组
- 依次遍历数组中的每个元素,随机一个索引数据,让当前元素与该索引位置处的元素进行交换。
 public class Test04 { public static void main(String[] args) { //目标:键盘录入一组工号,最终要随机输出一组出来作为排名 //1.动态初始化一个数组,存储5个工号 int[] codes = new int[5]; //2.定义一个循环,遍历数组,依次录入一个工号存入对应的位置 Scanner sc = new Scanner(System.in); for (int i = 0; i < codes.length; i++) { //正式录入工号 System.out.println("请您输入第"+(i+1)+"个员工的工号:"); int code = sc.nextInt(); //存入到数组中去 codes[i] = code; } //3.遍历数组中的每个元素,然后随机一个索引出来,让该元素与随机索引位置处的元素值进行交换(重点) Random r = new Random(); for (int i = 0; i < codes.length; i++) { //当前遍历的元素值:code[i] //随机一个索引位置出来:codes[index]; int index = r.nextInt(codes.length); //定义一个临时变量存储index位置处的值 int temp = codes[index]; codes[index] = codes[i]; codes[i] = temp; } //遍历数组元素输出就是随机排名的结果 for (int i = 0; i < codes.length; i++) { System.out.print(codes[i] + "\t"); } } }总结: 如何实现随机排名 - 定义一个动态初始化的数组用于录入数据。
- 遍历数组中的每个元素,每次随机一个索引值,让当前元素与该索引位置处的元素进行交换。
 
-  数组排序 数组排序就是对数组中的元素,进行升序(由小到大)或者降序(由大到小)的操作。 数组排序的技术 - 冒泡排序
- 选择排序
- 快速排序
- 插入排序
- …
 数组搜索相关的技术 - 二分搜索
- 分块查找
- 哈希表查找
- …
 冒泡排序思路 - 每次从数组中找出最大值放在数组中的最后面去(每个索引的数据都比较一遍)
 实现冒泡排序的步骤分析 -  确定总共需要做几轮:数组的长度-1 
-  每轮做几次: i(轮数) 次数 次数规律 1 3 数组的长度-1 2 2 3 1 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bs10o9Ms-1668566772252)(C:\Users\邢金政\Pictures\冒泡排序.png)] 
 public class Test05 { public static void main(String[] args) { //定义一个数组,存储一些数据 int[] arr = {5,2,3,1}; // 0,1,2,3 //2.定义一个循环控制比较的轮数 for (int i = 0; i < arr.length -1; i++) { //i = 0 时 比较3次 j = 0,1,2 //i = 1 时 比较2次 j = 0,1 //i = 2 时 比较1次 j = 0 for (int j = 0; j <arr.length - i -1; j++) { //判断j当前位置的索引值 是否 大于后一个位置 若较大 则交换 if(arr[j] > arr[j+1]){ int temp = arr[j+1]; arr[j+1] = arr[j]; arr[j] = temp; } } } //遍历数组内容输出 for (int i = 0; i < arr.length; i++) { System.out.print(arr[i]+"\t"); } } }总结 冒泡排序的思想 - 从头开始两两比较,把较大的元素与较小的元素进行交换
- 每轮把当前最大的一个元素存入到数组当前的末尾。
 冒泡排序的实现步骤 - 定义一个外部循环控制总共需要判断几轮(数组的长度-1)
- 定义一个内部循环,控制每轮一次往后比较几个位置(数组长度 -i-1)
 
数组的内存原理
Java内存分配、数组内存图
Java内存分配介绍
- 栈
- 堆
- 方法区
- 本地方法栈
- 寄存器


两个变量指向同一个数组对象 
 
数组使用常见问题
问题1:如果访问的元素位置超过最大索引,执行时会出现ArrayIndexOutBoundsException(数组索引越界异常)
public class Test06 { public static void main(String[] args) { int[] arr ={11,22,33}; System.out.println(arr[2]);//33 System.out.println(arr[3]);//Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3 } }
问题2:如果数组变量中没有存储数组的地址,而是null,在访问数组信息是会出现NullPointerException(空指针异常)
public class Test06 { public static void main(String[] args) { int[] arr ={11,22,33}; System.out.println(arr[2]);//33 arr = null; System.out.println(arr);//null //System.out.println(arr.length);//Exception in thread "main" java.lang.NullPointerException } }




















