本文仅作为个人笔记
数组
数组的引入
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.如何访问数组的长度
数组名称.length
3.数组的最大索引怎么获取?
数组的最大索引:数组名.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 } }