一、认识数组
数组就是一个容器,用来存储一批同种类型的数据。
数组的格式
1、完整格式:
数据类型[ ] 数组名 = new 数据类型 [ ] {元素1,元素2,元素3…};
2、简化格式:
数据类型[ ] 数组名 = { 元素1,元素2,......} ;
有变量,为什么还用数组?
1、假设用变量解决随机点名的需求:
代码繁琐,大量变量的定义。实现需求繁琐
2、用数组解决点名的需求:
代码简洁,逻辑清晰
遇到批量数据的存储和操作时,数组比变量更合适。
二、数组的定义和访问
1、静态初始化数组
定义数组的时候直接给数组赋值。
特点:在定义数组的同时,为数组确定了数据
package com.itchinajie.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、数组的访问
数组名称[索引]:可以访问数组中的元素进行取值 int data = arr[i](索引是数组中的元素从0开始从左到右的排序)
也可以对其进行赋值 arr[i] = 222;
数组名称.length:访问数组长度
最大索引:因为是先从0开始记数,所以做大索引是length - 1。
注意:访问数组时超过最大索引就会出现bug。
下面展示一些代码,让大家感受一下,最好自己敲一遍:
package com.itchinajie.define;
public class ArrayDemo2 {
public static void main(String[] args) {
//掌握数组的访问
int[] arr = {12,24,36};
//1.访问数组的全部数据
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
//System.out.println(arr[3]);会报错
//2.修改数组中的数据
arr[0] = 66;
arr[2] = 100;
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
//3.访问数组中的元素个数:数组名.length
System.out.println(arr.length);
//技巧:获取数组的最大索引:arr.length - 1 (前提是数组中存在数据)
System.out.println(arr.length - 1);
int[] arr2 = {10,20,30,40,50,60};
System.out.println(arr2.length - 1);
}
}
2、数组的长度 arr.length遍历
遍历:就是一个一个数据访问。
直接代码展示:
package com.itchinajie.define;
public class AarryDemo3 {
public static void main(String[] args) {
//掌握数据的遍历。
int[] ages = {12,24,36};
//0 1 2
//System.out.println(arr[0]);
//System.out.println(arr[1]);
//System.out.println(arr[2]);
//上面是这样写太繁琐
for (int i = 0; i < ages.length; i++) {
System.out.println(ages[i]);
}
}
}
通过遍历数组可以方便我们对批量元素进行求和、元素搜索、求最大值、最小值等。
3、案例训练
我们可以通过一个案例来感受一下数组的用途:
需求:
某部门5名员工的销售额分别是:16、26、36、6、100,请计算出他们部门的总销售额。
分析:
1、把这5个数据拿到程序中去 ---> 使用数组
int[ ] money = {16,26,36,6,188};
2、遍历数组中的每个数据,然后在外面定义求和变量把他们累加起来。
答案:
package com.itchinajie.define;
public class ArrayText1 {
public static void main(String[] args) {
//案例需求:某部门5名员工的销售额分别是:16、26、36、6、100,请算出他们部门的销售总额。
//1.把这五个数据拿到 程序中去
int[] money = {16,26,36,6,100};
//2.遍历数组中的每个数据,然后在外面定义求和变量把他们累加起来。
//定义一个变量用于累加求和
int sum = 0;
for (int i = 0; i < money.length; i++) {
System.out.println(money[i]);
sum += money[i];
}
//输出结果
System.out.println("该部门的销售总额为:" + sum);
}
}
2、动态初始化数组
数组的动态初始化
定义数组时先不存入具体元素值,只确定数组存储数据类型的数组的长度。
格式:
//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]);
//需要手动定义值
ages[0] = 12;
ages[1] = 18;
ages[2] = 32;
System.out.println(ages[0]);
System.out.println(ages[1]);
System.out.println(ages[2]);
System.out.println("-------------------------------");
动态初始化数组的默认规则
byte、short、int、char、long类型数组的元素默认值都是0。
float、double类型数组元素的默认值都是0.0。
boolean类型数组的元素默认值是false、String类型数组的元素的默认值是null。
//动态初始化数组元素默认规则:
char[] chars = new char[3];
System.out.println((int)chars[0]);//转成int类型才能看到
System.out.println(chars[1]);
double[] doubles = new double[3];
System.out.println(doubles[0]);
boolean[] booleans = new boolean[3];
System.out.println(booleans[1]);
3、评委打分案例
需求
某歌唱比赛,需要开发一个系统:可以录入6名评委的打分,录入完毕后立即输出平均分做为选手得分。
分析:
1、6名评委的打分是后期录入的,一开始不知道具体的分数,因此定义一个动态初始化的数组存分数。
double[ ] = scores new double[6];
2、遍历数组中的每个位置,每次提示用户录入一个评委的分数,并存入到数组对应的位置。
3、遍历数组中的每个元素进行求和,最终算出平均分打印出来即可。
答案:
package com.itchinajie.define;
import java.util.Scanner;
public class ArrayText2 {
public static void main(String[] args) {
//案例需求:某唱歌比赛,需要开发一个系统:可以录入6名评委的打分,录入完毕后立即输出平均分做为选手得分。
//
double[] scores = new double[6];
Scanner sc = new Scanner(System.in);
for (int i = 0;i < scores.length;i++){
System.out.println("请输入第" + (i + 1) + "位评委所打分数:");
double score = sc.nextDouble();
scores[i] = score;
}
double sum = 0;
for(int i = 0;i < scores.length;i++){
sum += scores[i];
}
System.out.println("选手最终得分是:" + sum / scores.length);
}
}
三、数组的执行原理,Java程序的执行原理(了解)
java内存分配,基本类型的变量、数组在计算机中得到执行原理
1. 运行一个Java程序,主要看JVM中包含的哪几个部分内存区域?
方法区:放class文件的
栈内存: 运行的方法,main方法,定义的变量
堆内存:new出来的对象都在堆内存中
Java内存分配:
1、方法区(Java 8开始,方法区被元空间(Metaspace)所取代):
- 方法区是Java虚拟机的一部分,用于存储类的元信息、常量池、静态变量和编译器优化后的代 码等。
- 方法区是所有线程共享的内存区域,在Java虚拟机启动时被创建。
- 在方法区中,类的元信息包括类的名称、父类和实现的接口、字段和方法信息等。
- 常量池用于存储常量、字符串字面量、符号引用等。
- 静态变量存储在方法区中,被所有实例共享。
- 编译器优化后的代码存储在方法区,包括字节码和即时编译(JIT)生成的本地代码。
2. 堆内存(Heap Memory):
- 堆内存用于存储对象实例和数组等动态分配的数据。
- 所有通过关键字 `new` 创建的对象都存储在堆内存中(后面会经常见到)。
- 堆内存由Java虚拟机(JVM)自动管理,包括对象的分配、回收和垃圾回收等操作。
- 堆内存的大小可以通过JVM参数进行调整,一般比较大,用于存储动态分配的数据。
3. 栈内存(Stack Memory):
- 栈内存用于存储方法调用的栈帧(stack frame)、局部变量和方法参数等数据。
- 每个线程在执行时都会有自己的栈内存,用于存储方法调用的信息。
- 栈内存中的数据是线程私有的,不同线程之间的栈内存互不干扰。
- 栈内存的大小是有限的,一般比较小,用于存储方法调用时的临时数据。
2.简单说说int a = 20; int[ ] arr = new int [ 3] 这两行代码的执行原理?
a是变量,直接放在栈中,a变量中存储的数据就是20这个值。
new int [ 3]是创建一个数组对象,会在堆内存中开辟区域存储3个整数。
arr是变量,在栈中,arr中存储的是数组对象在堆内存中的地址值。
多个变量指向同一个数组的问题
1.多个数组变量,指向同一个数组对象的原因是什么?需要注意什么?
多个数组变量中存储的同一个数组对象的地址。
多个变量修改的都是同一个数组对象中的数据。
2.如果某个数组变量中存储的null,代表什么意思?需要注意什么?
代表这个数组变量没有指向数组对象。
可以输出这个变量,但是不能用这个数组变量去访问数据或者访问数组长度,会报空指针异常:NullPointerException。
多个变量指向同一个数组:
使用数组时常见的一个问题:如果某个数组变量存储的地址是null,那么该变量将不再指向任何数组对象。
详细介绍请转以下链接:
四、专项训练:数组的常见案例
1、求最值:
实现步骤:
1、把数据拿到程序中去,用数组装起来。
int[ ] arr = {15,9000,10000,20000,9500,-5};
2、定义一个变量用于记录最终的最大值。
int max= arr[0];
3、从第二个位置开始:遍历数组的数据,如果遍历的当前
数据大于max变量存储的数据,则替换变量存储的数据为当前数据。
4、循环结束后输出max变量即可。
package com.itchinajie.Demo;
public class Test1 {
public static void main(String[] args) {
//掌握数组元素求最值
//1.把数据拿到程序中来,用数组装起来
int[] arr = {15,9000,10000,20000,9500,-5};
//2.定义一个变量用于记住最大值
int max = arr[0];
for (int i = 1;i < arr.length;i++){
if (arr[i] > max){
max = arr[i];
}
}
System.out.println("最高颜值是:" + max);
}
}
2、数组反转:
需求
某个数组有5个数据:10,20,30,40,50,请将这个数组中的数据进行反转。
[10,20,30,40,50]反转后[50,40,30,20,10]
分析:
数组的反转操作实际上就是:依次前后交换数据即可实现。
package com.itchinajie.Demo;
public class Test2 {
public static void main(String[] args) {
//掌握数组的反转
//1.准备一个数组
int[] arr = {10,20,30,40,50};
//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.print(arr[i] + " ");
}
}
}
3、随机排名:
需求
某公司开发部5名开发人员,要进行项目进展汇报演讲,现在采取随机排名后进行汇报。请先依次录入5名员工的工号,然后展示出一组随机的排名顺序。
分析:
1、在程序中录入5名员工的工号存储起来-->使用动态初始化数组的方式。
2、依次遍历数组中的每个数据。
3、每遍历到一个数据,都随机一个索引值出来,让当前数据与该索引位置处的数据进行交换。
package com.itchinajie.Demo;
import java.util.Random;
import java.util.Scanner;
public class Test3 {
public static void main(String[] args) {
//完成随机排名
//1.定义一个动态初始化的数组用于存储5名员工的工号
int[] codes = new int[5];
//2.提示用户录入5名员工的工号
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++) {
//每遍历到一个数据,都随机一个数组索引范围内的值,然后让当前遍历的数据与该索引位置处的值进行交换。
int index = r.nextInt(codes.length);
//定义一个临时变量记住index位置处的值
int temp = codes[index];
//把i位置处的值赋值给index位置处
codes[index] = codes[i];
codes [i] = temp;
}
//4.遍历数组中的工号输出即可
for (int i = 0; i < codes.length; i++) {
System.out.println(codes[i] + " ");
}
}
}
五、Debug工具的使用:
debug工具:IDEA自带的断电调试工具,可以控制代码从断点开始一行一行的执行,然后详细观看程序执行的情况。