一、认识数组
1.数组是什么?
- 数组是一个容器,用来存储一批同种类型的数据
例子:
int[] arr = {20,10,80,60,90};
String[] names = {"牛二","西门","全蛋"}
2.有变量,为什么还用数组?
- 假设用变量解决随机点名的需求:
现在有七十名学生:
- 用数组解决随机点名的需求:
- 结论:遇到批量数据的存储和操作时,数组比变量更适合
二、数组的定义和访问
1.静态初始化数组
- 定义数组的时候之间给数组赋值
- 静态初始化数组的格式:
package define;
public class ArrayDemo1 {
public static void main(String[] args) {
//目标:掌握数组的定义方式一:静态初始化
// 1. 数据类型[] 数组名 = new 数据类型[]{元素1, 元素2, 元素3,...}
int[] ages = new int[]{12, 24, 36};
double[] scores = new double[]{89.9, 99.5, 59.5, 88};
// 2. 简化写法:最好用这种
//数据类型[] 数据名 = {元素1, 元素2, 元素3,...}
int[] ages2 = {12, 24, 36};
double[] scores2 = {89.9, 99.5, 59.5, 88};
// 3. 数据类型[] 数组名 也可以写成 数据类型 数组名[]
int ages3[] = {12, 24, 36};
double scores3[] = {89.9, 99.5, 59.5, 88};
}
}
注意:
- “数据类型[] 数组名” 也可以写成 “数据类型 数组名[] ”
-
什么类型的数组只能存放什么类型的数据
数组在计算机中的基本原理:数组变量存储着右边数组对象的地址
由上面的演示可得出地址;数组是被称为引用数据类型
注意:数组变量名中存储的是数组在内存中的地址,数组是一种引用数据类型
(1)数组的访问
- 数组名[索引]
//取值
System.out.println(arr[0]);//12
//赋值
arr[2] = 100;
System.out.println(arr[2]);//100
- 数组的长度属性:length
//获取数组的长度(就是数组元素的个数)
System.out.println(arr.length); // 3
package define;
public class ArrayDemo2 {
public static void main(String[] args) {
//目标: 掌握数组的访问
int[] arr = {12,24,36};
//0 1 2
// 1. 访问数组的全部数据
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
//System.out.println(arr[3]);//没有第四个数据,会报错
System.out.println("--------------------");
// 2. 修改数组中的数据
arr[0] = 66;
arr[2] = 100;
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println("-------------------------");
// 3. 访问数组的元素个数:数组名.length
System.out.println(arr.length);
System.out.println("-------------------------");
// 4. 技巧:获取数组的最大索引:数组长度 - 1(前提是数组中存在数据)
System.out.println(arr.length - 1);
int[] arr2 = {};
System.out.println(arr2.length - 1);// -1 所以数组里有数据才适用上面的规则
}
}
(2)数组的遍历
- 遍历:就是一个一个数据的访问
- 为什么要遍历数组?为了求和、元素搜索、找最大值和最小值更方便
- 便利的写for循环的方法:
package define;
public class ArrayDemo3 {
public static void main(String[] args) {
//目标:掌握数组的遍历
int[] ages = {12,24,36};
// 0 1 2
/**这种遍历方式不靠谱
System.out.println(ages[0]);
System.out.println(ages[1]);
System.out.println(ages[2]);
*/
//可以采用循环的方式
for (int i = 0; i < ages.length; i++){//终极写法
//原本的写法:(int i = 0; i < 3; i++)
// i = 0 1 2
System.out.println(ages[i]);
}
//便利的写for循环:ages.fori
}
}
(3)案例训练-求和
需求:
- 某部门5名员工的销售额分别是:16、26、36、6、100,请计算出他们部门的总销售额。
分析:
- 把这5个数据拿到程序中去 ---> 使用数组
int[] money = {16,26,36,6,100};
- 遍历数组中的每个数据,然后在外面定义求和遍历把他们累加起来
package define;
public class ArrayTest4 {
public static void main(String[] args) {
// 目标:完成对数组元素的求和
// 1. 定义一个数组存储5名员工的销售额
int[] money = {16,26,36,6,100};
// 0 1 2 3 4
// 3. 定义一个遍历用于累加求和
int sum = 0;
// 2. 遍历这个数组中的每个数据
for (int i = 0; i < money.length; i++) {
System.out.println(money[i]);
sum += money[i];
}
System.out.println("员工的销售总额:" + sum);
}
}
2.动态初始化数组
- 定义数组时先不存入具体的元素值,只确定数组存储的数据类型和数组的长度
数组的动态初始化格式:
数据类型[] 数组名 = new 数据类型[长度];
int[] arr = new int[3];
//后赋值
arr[0] = 10;
System.out.println(arr[0]);
注意:
- 静态初始化和动态初始化数组的写法是独立的,不可以混用
动态初始化数组元素默认值规则:
package define;
public class ArrayDemo5 {
public static void main(String[] args) {
//目标:掌握定义数组的方式二:动态初始化数组
// 1. 数据类型[] 数组名 = new 数据类型[长度]
int[] ages = new int[3]; // ages = [0,0,0]
System.out.println(ages[0]);
System.out.println(ages[1]);
System.out.println(ages[2]);
System.out.println("----------");
ages[0] = 12;
ages[1] = 18;
ages[2] = 22;
System.out.println(ages[0]);
System.out.println(ages[1]);
System.out.println(ages[2]);
System.out.println("-------------------");
//查看字符类型的数组默认值
char[] chars = new char[3];//{0,0,0}
System.out.println((int)chars[0]);
System.out.println(chars[2]);
//0输出的字符在计算机里面是不显示的,可以强制把它转成int类型就能输出0了
System.out.println("-------------------");
//查看浮点型的数组默认值
double[] scores = new double[80];
System.out.println(scores[0]);
System.out.println(scores[79]);
System.out.println("-----------------");
//查看布尔型的数组默认值
boolean[] flags = new boolean[100];
System.out.println(flags[0]);
System.out.println(flags[99]);
System.out.println("----------");
String[] names = new String[80];
System.out.println(names[0]);
System.out.println(names[79]);
}
}
(1)案例训练-评委打分案例
需求:
- 某歌唱比赛,需要开发一个系统:可以录入6名评委的打分,录入完毕后立即输出平均分作为选手得分
分析:
- 6名评委的打分是后期录入的,一开始不知道具体的份数,因此定义一个动态初始化的数组存分数
double[] scores = new double[6];
- 遍历数组中的每个位置。每次提示用户录入一个评委的分数,并存入到数组对应的位置
- 遍历数组中的每个元素进行求和,最终算出平均分打印出来即可
package define;
import java.util.Scanner;
public class ArrayTest6 {
public static void main(String[] args) {
//目标:完成评委打分的案例
// 1. 定义一个动态初始化的数组,负责后期存储6个评委的打分
double[] scores = new double[6];
Scanner sc = new Scanner(System.in);
// 2. 遍历数组中的每个位置,录入评委的分数,存入到数组中去
for (int i = 0; i < scores.length; i++) {
System.out.println("请输入第" + (i+1) + "个评委的分数:");
scores[i] = sc.nextDouble();
System.out.println("第" + (i+1) +"个评委的分数:" +scores[i]);
}
// 3. 遍历数组中的每个元素进行求和
double sum = 0;
for (int i = 0; i < scores.length; i++) {
sum += scores[i];
}
System.out.println("总分为;" + sum);
double average = sum/scores.length;
System.out.println("平均分为:" + average);
}
}
三、数组在计算机中的执行原理
1.数组的执行原理,Java程序的执行原理
Java内存分配介绍(只看前三个):
- 方法区
- 堆
- 栈
- 本地方法栈
- 程序计数器
package memory;
public class ArrayDemo1 {
public static void main(String[] args) {
//目标:掌握普通变量,数组在计算机中的执行原理,Java程序在计算机中的执行过程
int a = 20;
System.out.println(a);
int[] arr = new int[]{11,22,33};
System.out.println(arr);
System.out.println(arr[1]);
//以前修改数组的方式:直接修改
arr[0] = 44;
arr[1] = 55;
arr[2] = 66;
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
}
}
简单总结int a = 20; int[] arr = new int[3] 这两行代码的运行原理
- a是变量,直接放在栈中,a变量中存储的数据就是20这个值
- new int[3]是创建一个数组对象,会在堆内存中开辟区域存储3个整数
- arr是变量,在栈中,arr中存储的是数组对象在堆内存中的地址值
2.多个遍历指向同一个数组的问题
package memory;
public class ArrayDemo2 {
public static void main(String[] args) {
//目标:认识多个变量指向同一个数组对象的形式,并掌握其注意事项/
int[] arr1 = {11,22,33};
// 把int类型的数组变量arr1赋值给int类型的数组变量arr2
int[] arr2 = arr1;//同类型的变量是可以直接赋值的
System.out.println(arr1);
System.out.println(arr2);//这两个数组对象都是一个地址
arr2[1] = 99;
System.out.println(arr1[1]);
}
}
使用数组时常见的一个问题:
- 如果是某个数组变量存储的地址是null,那么该变量将不再指向任何数组对象
arr2 = null; // 把null赋值给arr2
System.out.println(arr2); //null
System.out.println(arr2[0]); // 会出异常
System.out.println(arr2.length); //会出异常,不指向任何数组对象
四、专项训练:数组常见案例
1.数组求最值
需求:
现有六个颜色分数不一样的美女,最颜值最大的
实现步骤:
- 把颜值数据拿到程序中去,用数组装起来。
int[] faceScores = {15,9000,10000,20000,9500,-5};
- 定义一个变量用于记录最终的最大值
int max = faceScores[0];//建议存储数组的第一个元素值作为参照
- 从第二个位置开始:遍历数组的数据,如果遍历的当前数据大于max变量存储的数据,则替换变量存储的数据为当前数据
package demo;
public class Test1 {
public static void main(String[] args) {
// 目标:掌握数组元素求最值
// 1. 把颜值数据拿到程序中来,用数组装起来
int[] faceScores = {15,9000,10000,20000,9500,-5};
//0 1 2 3 4 5
// 2. 定义一个变量用于最终记住最大值
//不能写 int max = 0;因为里面的值要是负的,0就最大了
int max = faceScores[0];//建议用数组的第一个元素作为参照值
// 3,从数组的第二个位置开始遍历
for (int i = 1; i < faceScores.length; i++) {
//判断一下当前遍历的这个数据,是否大于最大值遍历max存储的数据。
//如果大于,当前遍历的数据需要赋值给max
if(max < faceScores[i]) {
max = faceScores[i];
// faceScores[0] = max;
// }else{
// max = faceScores[0];
// }//可以省略
}
}
System.out.println("颜值最大值为:" + max);
}
}
2.数组反转
需求:
- 某个数组有5个数据:10,20,30,40,50,请将这个数组中的数据进行反转。
[10,20,30,40,50] 反转后 [50,40,30,20,10]
分析:
- 数组的反转操作实际上就是:依次前后交换数据即可实现
package demo;
public class Test2 {
public static void main(String[] args) {
// 目标;完成数组反转。
// 1. 准备一个数组
int[] arr = {10,20,30,40,50};
// 2. 定义一个循环,设计2个变量,一个在前,一个在后
for (int i = 0, j = arr.length - 1; i < j; i++,j--) {
// arr[i] arr[j]
// 变量
// 1. 定义一个临时变量记住后一个位置处的值
int temp = arr[j];
// 2. 把前一个位置处的值赋值给后一个位置了
arr[j] = arr[i];
// 3. 把临时变量中记住的后一个位置处的值赋值给前一个位置处
arr[i] = temp;
}
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i] + " ");
}
}
}
3.随机排名
需求:
- 某公司开发部5名员工,要进行项目进展汇报演讲,现在采取随机排名后进行汇报。请先依次录入5名员工的工号,然后展示出一组随机的排名顺序。
分析:
- 在程序中录入5名员工的工号存储起来 -----> 使用动态初始化数组的方式。
- 依次遍历数组中的每个数据
- 每遍历到一个数据,都随机一个索引值出来,让当前数据与该索引位置处的数据进行交换
五、补充知识:Debug工具的使用
Debug工具
- IDEA自带的断点调试工具,可以控制代码从断点开始一行一行的执行,然后详细观看程序执行的情况。