Java大数据开发和安全开发
- (一)Java的数组
- 1.1 静态初始化数组
- 1.1.1 静态数组的定义
- 1.1.2 数组的原理
- 1.1.3 数组的访问
- 1.1.3.1 数组的取值
- 1.1.3.2 数组的赋值
- 1.1.3.3 数组的长度
- 1.1.3.4 数组的使用
- 1.1.4 数组的遍历
- 1.1.3 数组的案例
- 1.2 动态初始化数组
- 1.2.1 动态初始化数组的定义
- 1.2.1 数组的案例
- 1.3 数组的执行原理,Java程序的执行原理
- 1.3.1 **多个变量指向同一个数组的问题**
- 1.3.2 使用数组时常见的一个问题
- 数组执行原理总结
- 1.4 数组的练习案例
- 1.4.1 求最大值
- 1.4.2 数组反转
- 1.4.3 随机排名
- 1.5 debug工具的使用
- 1.5.1 第一步 设置断点
- 1.5.2 第二步 启动调试
- 1.5.3 第三步 介绍键位
- 1.5.3 第四步 单步执行
(一)Java的数组
- 数组就是一个容器,用来存储一批同种类型的数据
有变量,为什么还用数组?
- 下面是一个随机点名的系统
假设用变量解决随机点名的需求:
- 代码繁琐:大量变量的定义。 实现需求繁琐。
假设用数组解决随机点名的需求:
- 代码简洁。 逻辑清晰。
结论:遇到批量数据的存储和操作时,数组比变量更适合
1.1 静态初始化数组
1.1.1 静态数组的定义
- 定义数组的时候直接给数组赋值
静态初始化数组的格式:
注意
- “数据类型 [ ] 数组名”也可写成“数据类型 数组名[ ]”
- 什么类型的数组只能存放什么类型的数据。
public class ArrayDemo {
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.1.2 数组的原理
声明一个数组,首先是在内存中分出一块盒子,盒子内部分成两个区域,一个区域保存数组变量,一个区域保存数组的值,数组的值又分成三部分,每个部分独立存储一个数据,每个数据都有自己的下标被用来提供访问,数组的值在内存中以地址的形式被记录,变量中保存的也是数组的内存地址,访问数组的变量就会指向这个内存地址,从而找到数组的值,这也叫传值引用
验证数组变量的值的指向:
public class ArrayDemo {
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};
System.out.println(ages);
System.out.println(scores);
}
}
[I@4554617c //指向内存地址
[D@74a14482
注意:数组变量名中存储的是数组在内存中的地址,数组是一种引用数据类型
1.1.3 数组的访问
数组的访问
数组名
[索引]
1.1.3.1 数组的取值
/1 取值
System.out.println(arr[0]);//12
1.1.3.2 数组的赋值
// 赋值
arr[2]= 100;
System.out.println(arr[2]);//100
1.1.3.3 数组的长度
数组的长度属性:length
//获取数组的长度(就是数组元素的个数)
System.out.println(arr.length); //3
// 3、访问数组的元素个数:数组名.length
System.out.println(arr1.length);
// 技巧:获取数组的最大索引:arr.length-1(前提是数组中存在数据)
System.out.println(arr1.length-1);
int[] arr2 = {}; //并不是所有数组的长度都是length-1
System.out.println(arr2.length-1);
1.1.3.4 数组的使用
public class ArrayDemo1 {
public static void main(String[] args) {
//1 访问数组中的值
int[] arr1 = {12, 25, 63, 45};
System.out.println(arr1[0]);
System.out.println(arr1[1]);
System.out.println(arr1[2]);
System.out.println(arr1[3]);
//2 修改数组中的值
System.out.println(arr1[0]=21);
System.out.println(arr1[1]=22);
System.out.println(arr1[2]=23);
System.out.println(arr1[3]=24);
}
}
1.1.4 数组的遍历
- 遍历:就是一个一个数据的访问
public class ArrayDemo1 {
public static void main(String[] args) {
//1 访问数组中的值
int[] arr1 = {12, 25, 63, 45};
System.out.println(arr1[0]);
System.out.println(arr1[1]);
System.out.println(arr1[2]);
System.out.println(arr1[3]);
for (int i = 0; i < arr1.length;i++){
System.out.println(arr1[i]); //访问
}
//2 修改数组中的值
System.out.println(arr1[0]=21);
System.out.println(arr1[1]=22);
System.out.println(arr1[2]=23);
System.out.println(arr1[3]=24);
for (int i = 0; i < arr1.length;i++){
arr1[i] =i+1; //赋值
System.out.println(arr1[i]);
}
// 3、访问数组的元素个数:数组名.length
System.out.println(arr1.length);
// 技巧:获取数组的最大索引:arr.length-1(前提是数组中存在数据)
System.out.println(arr1.length-1);
int[] arr2 = {}; //并不是所有数组的长度都是length-1
System.out.println(arr2.length-1);
}
}
为什么要遍历数组?
- 求和 元素搜索 找最大值、最小值
1.1.3 数组的案例
public class ArrayDemo2 {
public static void main(String[] args) {
// 目标:完成对数组的元素求和。
// 1.定义一个数组存储5名员工的销售额
int[] arr1 = {16,26,36,6,100};
//3、定义一个变量用于累加求和
int sum = 0;
//2、遍历这个数组中的每个数据。
for (int i=0;i<arr1.length;i++){
sum += arr1[i];
}
System.out.println("员工的销售总额:" + sum);
}
}
1.2 动态初始化数组
1.2.1 动态初始化数组的定义
- 定义数组时先不存入具体的元素值,只确定数组存储的
数据类型
和数组的长度
- 静态初始化和动态初始化数组的写法是独立的,
不可以混用
数组的动态初始化格式:
import java.util.Random;
public class ArrayDemo3 {
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]);
ages[0]= 12;
ages[1]= 18;
ages[2]= 32;
System.out.println(ages[0]);
System.out.println(ages[1]);
System.out.println(ages[2]);
// 2、动态数组循环赋值 数据类型[]数组名=new 数据类型[长度]
int[] arr1 = new int[10];
for (int i=0; i<10;i++){
Random r = new Random();
int num = r.nextInt(10);
arr1[i] = num;
}
System.out.println(arr1.length);
}
}
动态初始化数组元素默认值规则:
public class ArrayDemo3 {
public static void main(String[] args) {
int[] age1 =new int[3]; //age1 =[0,0,0]
System.out.println(age1[0]);
System.out.println(age1[1]);
System.out.println(age1[2]);
char[]chars = new char[3];// [0,0,0]
System.out.println((int)chars[0]);
System.out.println((int)chars[2]);
double[] scores = new double[80];// [0.0, 0.0]
System.out.println(scores[0]);
System.out.println(scores[79]);
boolean[] flags = new boolean[100]; // [false, false]
System.out.println(flags[0]);
System.out.println(flags[99]);
String[] names = new String[80];// [null, null]
System.out.println(names[0]);
System.out.println(names[79]);
}
}
两种数组定义的方法各自适合什么业务场景?
- 动态初始化:适合开始不确定具体元素值,只知道元素个数的业务场景
- 静态初始化:适合一开始就知道要存入哪些元素值的业务场景
1.2.1 数组的案例
import java.util.Scanner;
public class ArrayDemo4 {
public static void main(String[] args) {
// 目标:完成评委打分的案例。
// 1、定义一个动态初始化的数组,负责后期存储6个评委的打分。
double[] scores = new double[6];
System.out.println(scores.length);
double sum =0;
Scanner sc = new Scanner(System.in);
// 2、遍历数组中的每个位置,录入评委的分数,存入到数组中去
for (int i=0;i<scores.length;i++){
System.out.println("请输入第" +(i+1)+"位裁判的评分");
double num = sc.nextDouble();
scores[i] = num;
}
//3、遍历数组中的每个元素进行求和
for (int j=0; j < scores.length;j++){
sum += scores[j];
}
System.out.println("选手的平均分为" + sum / scores.length);
}
}
1.3 数组的执行原理,Java程序的执行原理
- java程序在编译后会产生一个class文件
- Java程序运行时会把class文件放到内存中的JVM虚拟机中执行
- Java为了便于虚拟机运行class文件,将虚拟机中的内存区域进行了划分,划分成了方法区、栈、堆,本地方法栈、程序计数器
java程序运行时,会将class文件方法方法区,然后使用栈内存加载程序中的main方法,main中new出来的东西都放在堆内存中,并且拥有自己的内存地址
理解下面代码执行的顺序
public class ArrayDemo5 {
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]);
}
}
- ● a是变量,直接放在栈中,a变量中存储的数据就是20这个值。
- ● new int[3]是创建一个数组对象,会在堆内存中开辟区域存储3个整数
- ● arr是变量,在栈中,arr中存储的是数组对象在堆内存中的地址值,
1.3.1 多个变量指向同一个数组的问题
public class ArrayDemo6 {
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]);
}
}
1.3.2 使用数组时常见的一个问题
- 如果某个数组变量存储的地址是null,那么该变量将不再指向任何数组对象
数组执行原理总结
1、多个数组变量,指向同一个数组对象的原因是什么?需要注意什么?
- 多个数组变量中存储的是同一个数组对象的地址
- 多个变量修改的都是同一个数组对象中的数据。
2、如果某个数组变量中存储的nul,代表什么意思?需要注意什么?
- ●代表这个数组变量没有指向数组对象
- ●可以输出这个变量,但是不能用这个数组变量去访问数据或者访问数组长度,会报空指针异常:NullPointerException。
1.4 数组的练习案例
1.4.1 求最大值
- 把数据拿到程序中去,用数组装起来,
- 定义一个变量max用于记录最大值,
- max变量默认存储了第一个元素值作为参照物。
- 从第二个位置开始遍历数组的数据,如果当前元素大于变量存储的数据,则替换变量存储的值为该元素 循环结束后输出max变量即可,
import java.util.Random;
public class ArrayTest {
public static void main(String[] args) {
// 目标:掌握数组元素求最值。
// 1、把颜值数据拿到程序中来,用数组装起来
int[] faceScores = {15, 9000, 10000, 20000, 9500, -5};
// 2、定义一个变量用于最终记住最大值。
int max = faceScores[0];
//3、从数组的第二个位置开始遍历。
for (int i = 1; i < faceScores.length; i++) {
//i=1234 51! 判断一下当前遍历的这个数据,是否大于最大值变量max存储的数据,如果大于,当前遍历的数据需要赋值给max
if (faceScores[i] > max) {
max = faceScores[i];
}
}
System.out.println("最高颜值是:" + max);
//2
int[] arr1 = new int[10];
Random random = new Random();
for (int i = 0; i < arr1.length; i++) {
int num1 = random.nextInt(10 + 1);
arr1[i] = num1;
}
int num2 = arr1[0];
for (int i = 1; i < arr1.length; i++) {
if (arr1[i] > num2) {
num2 = arr1[i];
}
}
System.out.println(num2);
}
}
1.4.2 数组反转
需求
- 某个数组有5个数据:10,20,30,40,50,请将这个数组中的数据进行反转
- [10,20,30,40,50] 反转后 [50,40,30,20,10]
public class ArrayTest1 {
public static void main(String[] args) {
// 目标:完成数组反转。
// 1、准备一个数组
int[] arr ={10,20,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;
}
// 3、遍历数组中的每个数据,看是否反转成功了
for (int i=0;i < arr.length; i++){
System.out.print(arr[i] + " ");
}
}
}
1.4.3 随机排名
- 定义一个动态初始化的数组用于录入员工的工号
- 遍历数组中的每个元素。
- 每遍历到一个数据,都随机一个索引值出来,让当前数据与该索引位置处的数据进行交换
- 输出数组中的内容即可,
import java.util.Random;
import java.util.Scanner;
public class ArrayTest2 {
public static void main(String[] args) {
int[] arr1= new int[5];
Scanner sc = new Scanner(System.in);
for (int i=0;i < arr1.length;i++){
System.out.println("请输入第"+(i+1)+"员工");
int num =sc.nextInt();
arr1[i]=num;
}
Random random = new Random();
for (int i = 0; i < arr1.length; i++) {
int index = random.nextInt(arr1.length);
int temp = arr1[index];
arr1[index] = arr1[i];
arr1[i] = temp;
// arr1[i] = arr1[index];
}
for (int i = 0; i < arr1.length; i++) {
System.out.println(arr1[i]);
}
}
}
1.5 debug工具的使用
- IDEA自带的断点调试工具,可以控制代码从断点开始一行一行的执行,然后详细观看程序执行的情况。
1.5.1 第一步 设置断点
点击行号右边和代码区域左边的空白区域,也就是红色圆圈部分,生成断点,产生实体的红色圆型
1.5.2 第二步 启动调试
右键菜单选择debug +文件名
1.5.3 第三步 介绍键位
Step over:程序往下执行一行。
Step into:进入方法内,可以进入自定义方法或三方库方法,JDK 方法无法进入。
Force step into:强制进入方法内,一般 Step into 进不去时可以使用。
Step out:退出方法,跟 Force step into 配合使用。
Drop Frame:当我们 Debug 从 A 方法进入 B 方法时,通过降帧(退帧)可以返回到调用 B 方法前,这样我们就可以再一次调用 B 方法。
1.5.3 第四步 单步执行
断点打在这一行,表示代码即将执行这一行,也就是还未执行这一行,我们点击Step into,向下执行一行,
蓝光打在下一行表示上一行执行完毕,上一行红框内显示执行后的结果
控制台也会显示相应的执行结果
我们点击Step into,持续向下执行,会看见每一行都会在结尾显示代码的当前执行结果
这里我们就方便对比和观察for循环执行的效果,i=1和i=2的时候代码执行效果
点击console显示最终程序运行结果