【JavaSE 第六天】
一、 内存分析
1. 声明基本数据类型变量:
(栈内存可以类比于水杯,存储数据遵循:“先进后出,后进先出”)
int a = 10;
- 栈内存
变量名 | 变量 |
---|---|
a | 10 |
2. 创建对象
- 创建的对象身就是引用数据类型
在栈内存里面已经放不下了
就要放在堆内存
通过地址来联系(十六进制表示)
通过地址来引用(所以叫引用数据类型)
Scanner scanner = new Scanner(System.in);
- 栈内存
变量名 | 变量值 |
---|---|
a | 10 |
scanner | 0xEEFF60AA |
- 由栈内存里面的0xEEFF60AA 指向 堆内存里面的 Scanner 对象
0xEEFF60AA |
---|
Scanner对象 |
3. 创建数组对象
int[] ageArray;
ageArray=new int[3];
- 栈内存
变量名 | 变量值 |
---|---|
a | 10 |
scanner | 0xEEFF60AA |
ageArray | 0xBBAA00 |
- 创建对象是:由栈内存里面的 0xEEFF60AA 指向堆内存里面的 Scanner 对象
- 创建数组对象是:由栈内存里面的 0xBBAA00 指向 它所在的数据
0xEEFF60AA |
---|
Scanner对象 |
- 开始是默认值,当将数据写入数组时就会找到地址值在堆内存中改变值(数据)
0xBBAA00 |
---|
下标0:0 |
下标1:0 |
下标2:0 |
4. 转移变量(多声明一个数组变量)
当进行如下操作时:
int[] otherArray=ageArray;
-
它仅仅将变量值中的 地址值 传给了 otherArray 所以这时 otherArray 也会指向该地址值下的数据(就相当于多了一个访问数据的入口)
-
通过另一个变量访问数组元素仍然可以读取或者是更改数据
String[] arr = new String[3];
arr[1] = "刘杰";
arr = new String[5];
5. 数组变量指向新数组对象
- 栈内存中
原 arr |
---|
地址值:0x34ab |
- 堆内存
0x34ab |
---|
null |
刘杰 |
null |
- 栈内存中
现 arr |
---|
地址值:0x78cd |
- 堆内存
0x78cd |
---|
null |
null |
null |
null |
null |
就相当与整个变量的地址值更改并抛弃原地址(将来会被垃圾回收,释放掉,数据全部丢失)
6. 数组练习
练习一:
int[] arr=new int[]{8,2,1,0,3};
int[] index=new int[]{2,0,3,2,4,0,1,3,2,3,3};
String tel="";
for (int i = 0; i < index.length; i++) {
tel+=arr[index[i]];
}
System.out.println("联系方式:"+tel);
练习二:
去最值取平均值
int[] scoreArray;
scoreArray=new int[]{5,4,6,8,9,0,1,2,7,3};
int maxNum=scoreArray[0];
int minNum=scoreArray[0];
// 两个最值的初始值应该都是数组元素中的某一个值
// 例如否则初始为零会导致最小值出问题
for (int i = 0; i < scoreArray.length; i++) {
int score = scoreArray[i];
// 找出最大值
if(maxNum<score){
maxNum=score;
}
// 找出最小值
if(minNum>score){
minNum=score;
}
}
System.out.println("maxNum = " + maxNum);
System.out.println("minNum = " + minNum);
// 声明求和
int sum=0;
// 遍历累加
// 最高或最低值有多个需要考虑
for (int i = 0; i < scoreArray.length; i++) {
int score=scoreArray[i];
sum=sum+score;
}
sum=sum-minNum-maxNum;
int average=sum/(scoreArray.length-2);
System.out.println("sum = " + sum);
System.out.println("average = " + average);
练习三:
计算天数
// 创建数组 保留平年一个月的天数
int[] dayOfMonthArray={31,28,31,30,31,30,31,31,30,31,30,31};
//创建scanner对象
Scanner scanner=new Scanner(System.in);
//读取年份
System.out.println("请输入年份:");
int year= scanner.nextInt();
//读取月
System.out.println("请输入月份(1~12):");
int month=scanner.nextInt();
if(month<1||month>12){
System.out.println("输入不合法!");
return;
}
//读取日
System.out.println("请输入日期:");
int dayUser= scanner.nextInt();
if(dayUser<1||dayUser>31){
System.out.println("输入不合法!");
return;
}
// 声明一个变量用来保存天数累加的总结果
int sum=0;
// 在计算天数总和,分为整月部分和当前月
// 通过循环遍历整月部分
// 记录经过的整月
int pastMonth=month-1;
for (int i = 0; i < pastMonth; i++) {
// 进入循环需要累加整月
// 计算 month-1 对应的数组元素
// 数组下标为 i
int dayMonth=dayOfMonthArray[i];
// 累加天数
sum=sum+dayMonth;
}
// 计算当月部分
// 从dayOfMonth中找到当前月总天数
int dayMonth=dayOfMonthArray[month-1];
// 考虑简单情况
if(month==1||(month==2&&dayUser<=28)){
sum=sum+dayUser;
}else{
// 剩余情况就是2月29日当天及之后的天数
// 判断是否为闰年
if((year%4==0&&year%100!=0)||year%400==0){
if(month==2){
// 如果是闰年的二月份二十九日
dayMonth=dayMonth+1;
}else{
// 输入日期在2月29日之后就在总数加一
sum=sum+1;
}
}
if(dayUser>dayMonth){
System.out.print("数据不合法!");
return;
}
// 将输入指定的日期累加进结果
sum=sum+dayUser;
}
System.out.println("sum = " + sum);
练习四:
字母转换
// 将小写字母强转为int类型 查看字母底层编码值
//System.out.println((int)'a');
char[] wordArray=new char[26];
for (int i = 0; i <= 25; i++) {
wordArray[i]=(char)(i+97);
System.out.println("wordArray = ["+i+"]=" + wordArray[i]);
}
// 遍历数组打印大写字母
for (int i = 0; i < 26; i++) {
char word=wordArray[i];
// 当前字符 -32 为大写字母
char upperWord=(char)(word-32);
System.out.println("小写字母:"+word+"\tupperWord = " + upperWord);
}
练习五:
记录五个人的名字和成绩输出获得最值的姓名
String[] namesArray;
namesArray=new String[5];
int[] scoreArray;
scoreArray=new int[5];
Scanner scanner=new Scanner(System.in);
for (int i = 0;i < 5; i++) {
System.out.println("请输入姓名:");
String names = scanner.nextLine();
namesArray[i] = names;
}
for (int i = 0; i < 5; i++) {
System.out.println("请输入成绩:");
int score=scanner.nextInt();
scoreArray[i]=score;
}
int maxNum=scoreArray[0];
int minNum=scoreArray[0];
for (int i = 0; i < scoreArray.length; i++) {
if(maxNum<scoreArray[i]){
maxNum=scoreArray[i];
}
if(minNum>scoreArray[i]){
minNum=scoreArray[i];
}
}
for (int i = 0; i < 5; i++) {
if(maxNum==scoreArray[i]){
System.out.println("获得最高分的是:"+namesArray[i]);
}
if(minNum==scoreArray[i]){
System.out.println("获得最低分的是:"+namesArray[i]);
}
}
练习六:
/*
从键盘读入学生成绩,找出最高分,并输出学生成绩的等级
成绩大于等于最高分-10 等级为“A”
成绩大于等于最高分-20 等级为“B”
成绩大于等于最高分-30 等级为“C”
其余 等级为“D”
先读入学生人数,根据人数创建int数组,存放学生成绩
*/
// 1.根据输入的数据创建数组的对象
Scanner scanner=new Scanner(System.in);
// 读取用户输入的学生人数
System.out.println("请输入学生人数:");
int studentsCount= scanner.nextInt();
// 根据输入的学生人数创建数组对象
int[] scoreArray=new int[studentsCount];
// 将输入的数据保存到数组中
for (int i = 0; i < studentsCount; i++) {
// 读入输入
System.out.println("请输入第"+(i+1)+"名学生的成绩。");
int score=scanner.nextInt();
// 将学生成绩存入数组
scoreArray[i]=score;
}
// 2.查找输入数据的最大值
// 声明一个变量存储最大值
int maxScore=scoreArray[0];
// 遍历成绩的数组
for (int score : scoreArray) {
if (score > maxScore) {
maxScore = score;
}
}
System.out.println("maxScore = " + maxScore);
// 3.输出学生成绩的等级
// 遍历学生成绩的数组
for (int i = 0; i < scoreArray.length; i++) {
int score=scoreArray[i];
// 计算所属等级
if(score>=maxScore-10){
System.out.println("第"+(i+1)+"位学生成绩是A级");
}else if(score>=maxScore-20){
System.out.println("第"+(i+1)+"位学生成绩是B级");
}else if(score>=maxScore-30){
System.out.println("第"+(i+1)+"位学生成绩是C级");
}else{
System.out.println("第"+(i+1)+"位学生成绩是D级");
}
}
二、 多维数组
1. 概念
- 一维数组类比于数轴
- 二维数组类比于平面直角坐标系
- 三维数组类比于空间直角坐标系
2. 多维数组的底层是内存存储结构
int[][] numberArray = new int[3][2];
numberArray[0]=new int[2];
numberArray[0][0]=5;
- 栈内存
变量名 | 变量值 |
---|---|
numberArray | 0x5533AA |
- 堆内存
0x5533AA |
---|
下标0:0x6677BB |
下标1:null |
下标2:null |
- 下标0:0x6677BB 指向它地址下的值(数据)
0x6677BB |
---|
下标0:5 |
下标1:0 |
- 通俗讲就是一维数组是根本,数组里套着数组,最终的地址值下是一维数组下的数据(最终回到一维数组中)
理解:在多维数组声明并创建完毕后,需要 new (例如:格式2,格式3… … 另外只有在初始化完成后才能访问具体数据(读,写),具体参照下方“使用形式”)低一维度的数组,将他的地址值存入比他高一维度的“堆内存”中,之后就是一级一级的嵌套,直到最后是最终数据在一维数组中
(1) 对比:
一维数组
int[] arr;
arr = new int[3];
arr[0] = 5;
二维数组
int[][] arr;
arr = new int[2][];
arr[0] = new int[3];
arr[1] = new int[3];
arr[0][0] = 5;
3. 语法方面
格式1:
- 动态初始化
int[][] arr = new int[3][2]
解释:
(形状是矩形的)
- 定义了名称为 arr 的二维数组
- 二维数组中有三个一维数组
- 每一个一维数组中有两个元素
- 一维数组的名称分别为
arr[0]
,arr[1]
,arr[2]
- 给第一个一维数组“ 1 ”下角标位赋值“ 78 ”写法为:
arr[0][1]=78;
格式2:
- 动态初始化
int[][] arr = new int[3][];
(第二个维度没有限制长度)(形状可以是不规则的阶梯状)
- 二维数组中有三个一维数组
- 每一个一维数组都是默认初始化值 null (注意:区别于格式1)
- 可以对这个三个一维数组分别进行初始化
arr[0] = new int[3];
arr[1] = new int[1];
arr[2] = new int[2];
注意:(这是错误的写法:)
int[][] arr = new int[][3]; //这是非法的
格式3:
- 静态初始化
int[][] = new int[][]{3,8,2},{2,7}{9,0,1,6};
- 定义一个名称为 arr 的二维数组,二维数组中有三个一维数组
- 每一个一维数组中具体元素也都已初始化
第一个一维数组arr[0]={3,8,2}
第二个一维数组arr[1]={2,7}
第三个一维数组arr[2]={9,0,1,6}
- 第三个一维数组的长度表示方式:
arr[2].length;
(1) 特殊写法情况: x 是一维数组,y 是二维数组
int[] x,y[];
Java 中多维数组不必都是规则的矩阵形式
练习:使用形式:
// 一、声明二维数组变量并创建二维数组对象
// 格式1:动态初始化——创建数组对象时就指定了两个维度的数组长度
int[][] arr2d01 = new int[3][2];
arr2d01[0][0]=100;
arr2d01[0][1]=101;
arr2d01[1][0]=102;
arr2d01[1][1]=103;
arr2d01[2][0]=104;
arr2d01[2][1]=105;
// 格式2:动态初始化——仅仅指定第一个维度的数组长度
int[][] arr2d02=new int[3][];
arr2d02[0]=new int[]{3,5,7};
arr2d02[1]=new int[]{23,546,8,16};
arr2d02[2]=new int[]{23,45};
System.out.println();
// 格式3:静态初始化——在创建对象时对象将数据填充
// 此时如果某个元素位置设置为null不会编译报错,但是访问这个位置还是要先初始化
int[][] arr2d03=new int[][]{{1,2,3},{4,5},null,{6,7,8}};
// 前面设置为 null 的地方 必须要初始化
arr2d03[2]=new int[]{12,24};
// 更改第一个元素的值
arr2d03[2][0]=5;
// 格式4(特殊格式):声明变量时,两层[]没有在一起
int[] arr2d04[]=new int[][]{{1,2,3},{4,5},{6,7,8}};
System.out.println(); // 换行
// 二、访问二维数组元素(读,写)
int[][] arr2d05=new int[2][2];
// 向数组元素写入数据
arr2d05[1][0]=10;
// 读取数组元素
System.out.println("arr2d05[1][0] = " + arr2d05[1][0]);
遍历二维数组:
// 三、遍历二维数组 需要使用嵌套的循环
int[][] arr2d06=new int[][]{{1,2,3},{4,5,6},{7,8,9}};
// 先遍历第一个维度:取出每一个一维数组
for (int i = 0; i < arr2d06.length; i++) {
int[] intArr=arr2d06[i];
for (int j=0;j<intArr.length;j++){
int intValue=intArr[j];
System.out.println("intValue = ["+i+"]["+j+"]=" + intValue);
}
}
遍历数组求和:
int sum=0;
int[][] numberArray;
numberArray=new int[3][];
numberArray[0]=new int[]{3,5,8};
numberArray[1]=new int[]{12,9};
numberArray[2]=new int[]{7,0,6,4};
System.out.println("numberArray = " + numberArray.length);
for(int i=0;i < numberArray.length;i++){
int[] intArray=numberArray[i];
for(int j=0;j< intArray.length;j++){
int intValue=intArray[j];
sum=sum+intValue;
}
}
System.out.println("sum = " + sum);
4. 练习:
- 声明:
int[] x,y[];
在给 x,y 变量赋值以后,以下选项允许通过编译的是:
样式 | 是否编译通过 |
---|---|
x[0]=y; | no |
y[0]=x; | yes |
y[0][0]=x; | no |
x[0][0]=y; | no |
y[0][0]=x[0]; | yes |
x=y; | no |
解释:
- 一维数组:
int[] x
或者int x[]
- 二维数组:
int[][] y
或者int[] y[]
或者int y[][]
- 第一个
x[0]
是一维数组 y 是二维数组 - 第二个
y[0]
是二维数组的第一个维度是一维数组 x 是一维数组 - 第三个
y[0][0]
是二维数组 x 是一维数组 - 第三个
x[0][0]
本是一维数组这样写不合法 - 第四个
y[0][0]
是二维数组中的一维数组中的 int 类型数据x[0]
也是 int 类型的数据 - 第五个
x=y
一维数组与二维数组 写法不合法
杨辉三角练习
// 1.创建二维数组 第一维长度为十
int[][] yangHuiArray=new int[10][];
// 2.通过双层for循环给二维数组填充数据
for(int i=0;i< yangHuiArray.length;i++){
// 3.创建一维数组,对 下标 i 进行初始化
yangHuiArray[i]=new int[i+1];
// 4.遍历一维数组,填充数据
for (int j = 0; j <= i; j++) {
// 5.一头(一维数组的下标 0 的元素)一尾(一维数组的下标长度-1 的元素)固定是1
// 一维数组中最后一个元素的下标正好就是现在外层循环变量
if(j==0||j==i){
yangHuiArray[i][j]=1;
}else{
// 6.非头和尾的数是上一行中两个元素相加得到的
yangHuiArray[i][j]=yangHuiArray[i-1][j-1]+yangHuiArray[i-1][j];
}
}
}
// 7.遍历数组
for (int i = 0; i < yangHuiArray.length; i++) {
int[] yangHuiValueArray=yangHuiArray[i];
for(int j=0;j< yangHuiValueArray.length;j++){
System.out.print(yangHuiValueArray[j]+"\t");
}
System.out.println();
}