# 【数组】
##### 今日复习指南
~~~
1.简化格式初始化数组的使用(0.5个小时内完成,多写几遍)
Demo01UseArray.java
2.数组的遍历(0.5个小时内完成,多写几遍)
Demo01ArrayEach.java
3.数组的最大值(1个小时,多写几遍)
Demo03ArrayMax.java
~~~
##### 今日内容
~~~
数组的概念和数组变量的定义【重点】
数组的初始化及使用【重点的重点】 ---------------最核心的内容--------------
数组的内存图【理解】
数组的常见问题【理解】
数组的练习【重点的重点】 ---------------最核心的内容--------------
快捷键:
生产输出语句: 表达式.sout
数组遍历:
数组名.fori: 正着遍历
数组名.forr: 倒着遍历
~~~
### 第一章 数组定义和访问【理解】
##### 1.1 容器的概念
~~~
一个变量中只能存储存储一个数据,新的数据进来,老的数据被替换,如果要存储多个数据,需要使用容器
容器:是将多个数据存储到一起,每个数据称为该容器的元素。
生活中的容器:水杯,衣柜,鞋柜, 教室
数组:
1.概念: java中的数组就是一个容器,可以存储多个数据,但是这多个数据的类型必须保持一致
2.特点:
(1)可以存储多个数据
(2)多个数据的类型必须保持一致
(3)数组长度一旦创建,永远不可以发生改变
public class Demo01Box { //-----------------------此代码不用敲--------------------------------
public static void main(String[] args) {
//比如我们班有80个学生需要参加考试,每个学生对应一个成绩(整数)
//可以定义80个int变量
int a = 80;
int b = 90;
int c = 70;
int d = 50;
int e = 85;
int f = 95;
int g = 59;
int h = 63;
//需要求总分
int sum = a + b + c + d + e + f + g + h;
//需要求平均分
int avg = sum/80;
//需要求最高分和最低分: 实现起来非常麻烦
}
}
~~~
##### 1.2 数组变量的定义
~~~
数组变量: 专门用来存储数组容器的变量
1.数组变量定义格式一: 推荐使用的格式
数据类型[] 数组名称1;
2.数组变量定义格式二: 不推荐使用的格式
数据类型 数组名称[];
1.定义一个存储int类型数组的变量arrayA
2.定义一个存储double类型数组的变量arrayB
3.定义一个存储char类型数组的变量arrayC
int[] arrayA: 这里只是定义了一个用来存储数组容器的变量,相当于门牌 但是对应的教室现在/目前还没有
目前还没有创建出真正的数组容器
~~~
~~~
public class Demo02Array {
public static void main(String[] args) {
//定义int变量num,未赋值
int num;
//System.out.println(num);//错误: 变量中没有数据,不能使用
//1.定义一个存储int类型数组的变量arrayA
//int类型数组: 该容器只能存储int类型的数据
int[] arrayA;
//错误: 目前只是定义好了一个用来存储数组容器的变量,但是还没有向该变量中存储数组呢
//System.out.println(arrayA);
//2.定义一个存储double类型数组的变量arrayB
//double类型数组: 该容器只能存储double类型的数据
double arrayB[];
//3.定义一个存储char类型数组的变量arrayC
//char类型数组: 该容器只能存储char类型的数据
char[] arrayC;
}
}
~~~
##### 图解:
![](https://img.kancloud.cn/56/3e/563e393f73fba600ebf7b576884b59ae_1302x508.png)
##### 1.3 数组的第一种初始化方式
~~~
数组的第一种初始化方式(动态初始化,指定数组的长度)
1.格式:
数据类型[] 数组名称 = new 数据类型[长度];
2.格式解释:
(1)左侧数据类型: 表示数组容器中可以存储什么类型的数据
(2)左侧[]: 表示数组的意思
(3)数组名称: 就是给数组起个名字,方便找到对应的数组
(4)=: 把右侧的数组容器存储到左侧的数组变量中
=就是赋值,只是给数组变量赋的是数组容器在内存中的地址值
(5)new: 在内存中创建数组容器的过程
(6)右侧数据类型: 和左侧保持一致
(7)长度: 数组中可以存储多少个数据
3.练习:
(1)创建一个int类型的数组,可以存储3个int数据,给该数组起个名称叫做arrayA
(2)创建一个double类型的数组,可以存储7个double数据,给该数组起个名称叫做arrayB
(3)创建一个char类型的数组,可以存储5个char数据,给该数组起个名称叫做arrayC
~~~
~~~
public class Demo03Array {
public static void main(String[] args) {
//(1)创建一个int类型的数组,可以存储3个int数据,给该数组起个名称叫做arrayA
int[] arrayA = new int[3];
//(2)创建一个double类型的数组,可以存储7个double数据,给该数组起个名称叫做arrayB
double[] arrayB = new double[7];
//(3)创建一个char类型的数组,可以存储5个char数据,给该数组起个名称叫做arrayC
char[] arrayC = new char[5];
}
}
~~~
##### 1.4 数组的第二种初始化方式
~~~
数组的第二种初始化方式(标准格式静态初始化: 指定数组元素)
1.格式:
数据类型[] 数组名称 = new 数据类型[]{元素1,元素2,元素3...};
2.注意:
(1){}中的多个元素之间用逗号隔开,最后一个元素后面没有逗号
(2)右侧[]中不用写长度,JVM会根据{}中的元素数量,推导出长度
3.练习:
(1)创建一个int类型的数组,可以存储多个int数据100,200,300,给该数组起个名称叫做arrayA
(2)创建一个double类型的数组,可以存储多个double数据1.1,2.2,3.3,4.4,5.5,6.6,7.7,给该数组起个名称叫做arrayB
(3)创建一个char类型的数组,可以存储多个char数据'真','的','好','想','你',给该数组起个名称叫做arrayC
~~~
~~~
public class Demo04Array {
public static void main(String[] args) {
//(1)创建一个int类型的数组,可以存储多个int数据100,200,300,给该数组起个名称叫做arrayA
int[] arrayA = new int[]{100,200,300};
//(2)创建一个double类型的数组,可以存储多个double数据1.1,2.2,3.3,4.4,5.5,6.6,7.7,给该数组起个名称叫做arrayB
double[] arrayB = new double[]{1.1,2.2,3.3,4.4,5.5,6.6,7.7};
//(3)创建一个char类型的数组,可以存储多个char数据'真','的','好','想','你',给该数组起个名称叫做arrayC
char[] arrayC = new char[]{'真','的','好','想','你'};
}
}
~~~
##### 1.5 数组的第三种初始化方式
~~~
数组的第三种初始化方式(简化格式的静态初始化: 指定元素)
1.格式:
数据类型[] 数组名称 = {元素1,元素2,元素3...};
2.练习:
(1)创建一个int类型的数组,可以存储多个int数据100,200,300,给该数组起个名称叫做arrayA
(2)创建一个double类型的数组,可以存储多个double数据1.1,2.2,3.3,4.4,5.5,6.6,7.7,给该数组起个名称叫做arrayB
(3)创建一个char类型的数组,可以存储多个char数据'真','的','好','想','你',给该数组起个名称叫做arrayC
3.注意:
(1){}中的多个元素之间用逗号隔开,最后一个元素后面没有逗号
(2)不需要指定长度,JVM根据{}中元素的数量推导数组长度
(3)虽然没有写new,但是底层/内部仍然有new的过程
(4)对于动态初始化和标准格式的静态初始化数组,可以分成两步完成
(5)对于简化格式静态初始化方式,不可以分成两步完成 java中的规定
~~~
~~~
public class Demo05Array {
public static void main(String[] args) {
//(1)创建一个int类型的数组,可以存储多个int数据100,200,300,给该数组起个名称叫做arrayA
int[] arrayA = {100, 200, 300};
//(2)创建一个double类型的数组,可以存储多个double数据1.1,2.2,3.3,4.4,5.5,6.6,7.7,给该数组起个名称叫做arrayB
double[] arrayB = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7};
//(3)创建一个char类型的数组,可以存储多个char数据'真','的','好','想','你',给该数组起个名称叫做arrayC
char[] arrayC = {'真', '的', '好', '想', '你'};
int a;
a = 10;
System.out.println(a);
a = 20;
System.out.println(a);
int[] array;//定义存储一个int类型数组的变量array
array = new int[3];//把长度为3的int数组,存储到变量array中
array = new int[]{10,20,30,50};//把存储多个int数据的int数组,重新存储到变量array中
int[] arr /*= {100,200,300,500}*/;
//arr = {100,200,300,500};//错误: java中规定,简化格式静态初始化数据进行赋值时,不能分成两步完成
}
}
~~~
##### 1.6 数组的使用
~~~
/*
数组的使用 ============================================重点重点重点=========================================
1.数组名称: 代表数组在内存中的地址值,是一个16进制的整数数字
2.索引编号: 是一个整数数字
(1)数组中的每个数据,称之为数组元素
(2)数组为内部的每个元素进行了一个数字编号(整数数字),称为索引/角标
索引从0开始到最大值(数组长度 减 1)
3.数组元素:
数组名称[索引编号]
比如:
array[2]: 数组array中索引编号为2的元素
4.数组长度的获取:
每个数组内部都有一个length属性,保存数组用元素的个数
数组名称.length: 是一个int数字,代表数组的长度
注意: length后面是没有()的
*/
public class Demo01UseArray {
public static void main(String[] args) {
//int num = 10;
//System.out.println(num);//10
//创建int类型数组array,并初始化
int[] array = new int[]{100,200,300};//100的索引编号是0,200的索引编号是1,300的索引编号是2
//数组名称: 代表数组在内存中的地址值,是一个16进制的整数数字
System.out.println(array);//[I@1540e19d
//打印100
System.out.println(array[0]);//打印数组array中索引编号为0的元素的值: 100
//打印200
System.out.println(array[1]);//打印数组array中索引编号为1的元素的值: 200
//打印300
System.out.println(array[2]);//打印数组array中索引编号为2的元素的值: 300
System.out.println("---------------");
//把100修改为1000
array[0] = 1000;//把数字1000存储到array中索引编号为0的元素中
//把200修改为2000
array[1] = 2000;//把数字2000存储到array中索引编号为1的元素中
//把300修改为3000
array[2] = 3000;//把数字3000存储到array中索引编号为1的元素中
//打印1000
System.out.println(array[0]);//打印数组array中索引编号为0的元素的值: 1000
//打印2000
System.out.println(array[1]);//打印数组array中索引编号为1的元素的值: 2000
//打印3000
System.out.println(array[2]);//打印数组array中索引编号为2的元素的值: 3000
System.out.println("---------------");
//获取数组array的长度,是一个int数字,保存到int变量count中
int count = array.length;
System.out.println("数组长度: "+count);
System.out.println("数组长度: "+array.length);
System.out.println("---------------");
/*
array.length的值: 3
打印数组元素,数组元素的所有格式: 数组名[索引编号]
array[array.length-1]: 先计算array.length-1 ==> 3 - 1 ==> 2
上面的式子等价于array[2]: 3000
*/
System.out.println(array[array.length-1]);//3000
}
}
~~~
### 第二章 数组原理内存图【理解】
##### 2.1 java中的内存分配
~~~
1.方法区: 存储可以运行的class文件。
2.方法栈: 方法运行时使用的内存,比如main方法运行,进入方法栈中执行。
3.堆内存 存储对象或者数组,new来创建的,都存储在堆内存。
4.寄存器 给CPU使用,和我们开发无关 不关心
5.本地方法栈 JVM在使用操作系统功能的时候使用,和我们开发无关。 不关心
今天主要使用:
1.栈内存: 运行方法的,存储方法中定义的变量的
2.堆内存: 存储的是所有new出来的内容
~~~
##### 图解:
![](https://img.kancloud.cn/ae/af/aeaf9e2e29cd005685aedafaa4fafa78_1261x525.png)
##### 2.2 一个数组内存图
~~~
/*
一个数组的内存图解
1.数组名称: 数组在堆内存空间的地址值,16进制的整数数字
2.数组元素有默认值
(1)整数数组 0
(2)小数数组 0.0
(3)字符数组 空白字符
(4)布尔数组 false
(5)引用类型: null
3.注意:
(1)数组变量保存数组在堆内存中的地址值,通过地址值找到对应的数组
(2)数组元素都有索引编号,通过索引编号找到对应的元素
*/
public class Demo01OneArray {
public static void main(String[] args) {
//创建int类型数组one,长度为2
int[] one = new int[2];
System.out.println(one);//数组名称: 数组在堆内存空间的地址值,16进制的整数数字: [I@1540e19d
System.out.println(one[0]);//打印数组one中索引编号0对应的元素的值,默认值:0
System.out.println(one[1]);//打印数组one中索引编号1对应的元素的值,默认值:0
//把索引编号0对应的元素修改成100
one[0] = 100;//把数字100存储到数组one中索引编号为0的元素中
//把索引编号1对应的元素修改成200
one[1] = 200;//把数字200存储到数组one中索引编号为1的元素中
System.out.println(one);//数组名称: 数组在堆内存空间的地址值,16进制的整数数字: [I@1540e19d
System.out.println(one[0]);//打印数组one中索引编号0对应的元素的值:100
System.out.println(one[1]);//打印数组one中索引编号1对应的元素的值:200
}
}
~~~
##### 图解:
![](https://img.kancloud.cn/af/c2/afc2ede045666448d8011b52e9b867fb_1285x535.png)
##### 2.3 两个数组内存图
~~~
/*
两个数组的内存图解
1.数组名称: 数组在堆内存空间的地址值,16进制的整数数字
2.注意:
(1)数组变量保存数组在堆内存中的地址值,通过地址值找到对应的数组
(2)数组元素都有索引编号,通过索引编号找到对应的元素
有两个数组,相当有有两套房子
一套是北京延庆两居室的房子,one是打开北京延庆两居室的房子的钥匙
一套是北京平谷两居室的房子,two是打开北京平谷两居室的房子的钥匙
你拿着钥匙one: 只能打开北京延庆两居室的房子
你的对象拿着钥匙two: 只能打开北京平谷两居室的房子
*/
public class Demo02TwoArray {
public static void main(String[] args) {
//创建int类型数组one,长度为2
int[] one = new int[2];//你在北京延庆购买了一套两居室的房子,one就是打开这套房子的钥匙
System.out.println(one);
System.out.println(one[0]);
System.out.println(one[1]);
one[0] = 100;
one[1] = 200;
System.out.println(one[0]);
System.out.println(one[1]);
System.out.println("--------------");
//创建int类型数组two,长度为2
int[] two = new int[2];//你在北京平谷购买了一套两居室的房子,two就是打开这套房子的钥匙
System.out.println(two);
System.out.println(two[0]);
System.out.println(two[1]);
two[0] = 1000;
two[1] = 2000;
System.out.println(two[0]);
System.out.println(two[1]);
}
}
~~~
##### 图解:省略,就是把一个对象的内存图复制两份,每个数组之间没有任何关系
##### 2.4 两个变量指向一个数组
~~~
/*
一个数组两个引用(名称)的内存图解
1.数组名称: 数组在堆内存空间的地址值,16进制的整数数字
2.在使用数组名称进行赋值时,传递的都是数组在内存空间的地址值
3.注意:
(1)数组变量保存数组在堆内存中的地址值,通过地址值找到对应的数组
(2)数组元素都有索引编号,通过索引编号找到对应的元素
数组变量名one中保存的是数组在堆内存空间的地址值,把one的值赋值给新的数组变量two,
导致数组变量名one和two保存相同的地址值,操作的是堆内存空间的同一个数组
one相当于是打开北京延庆两居室的房子的钥匙,现在通过钥匙one又配了一个新的钥匙two
此时: 钥匙one和two打开的都是北京延庆两居室的房子
钥匙one: 你自己拿着
钥匙two: 你对象拿着
注意:
1.数组变量保存数组在堆内存空间的地址值
2.使用数组变量进行赋值时,传递的是地址值
3.one保存数组在堆内存空间的地址值
把one赋值给新的数组变量two之后,
导致one和two保存相同的地址值,操作的
是同一个数组,不管通过one还是two修改
数组,之后再通过one和two看到的一定是
修改后的
*/
public class Demo03SameArray {
public static void main(String[] args) {
//创建int类型数组one,长度为2
int[] one = new int[2];//你在北京延庆购买了一套两居室的房子,one就是打开这套房子的钥匙
one[0] = 100;
/*
数组变量名one中保存的是数组在堆内存空间的地址值,把one的值赋值给新的数组变量two,
导致数组变量名one和two保存相同的地址值,操作的是堆内存空间的同一个数组
one相当于是打开北京延庆两居室的房子的钥匙,现在通过钥匙one又配了一个新的钥匙two
此时: 钥匙one和two打开的都是北京延庆两居室的房子
钥匙one: 你自己拿着
钥匙two: 你对象拿着
*/
int[] two = one;
two[0] = 1000;
System.out.println(one[0]);//1000
System.out.println(two[0]);//1000
System.out.println(one);//[I@1540e19d
System.out.println(two);//[I@1540e19d
}
}
~~~
##### 图解:
![](https://img.kancloud.cn/69/c2/69c2039ee13ed2182f71c1fed3751988_1293x536.png)
### 第三章 数组操作的常见问题【了解】
##### 3.1 数组越界异常
~~~
数组操作的常见问题一:
数组索引越界(超出了范围)异常
1.问题描述: java中使用java.lang.ArrayIndexOutOfBoundsException类来描述索引越界异常
2.产生原因:
使用int数字作为索引编号时,该索引编号在数组中是不存在的
索引编号范围: 从0开始 到 最大值 ( 数组长度 减 1 one.length - 1 )
3.解决方案:
找到索引越界的数字,进行修改,不让该数字超出数组元素的索引范围
~~~
~~~
public class Demo01ArrayProblem {
public static void main(String[] args) {
//创建int数组one,并初始化
int[] one = new int[]{100, 200};//100编号是0,200的编号是1
System.out.println(one);//地址值: [I@1540e19d
System.out.println(one[0]);//100
System.out.println(one[1]);//200
//System.out.println(one[2]);//索引2不存在: 程序出现问题,停止了 报出数组索引越界异常
System.out.println("main...end...");
}
}
~~~
图解:
![](https://img.kancloud.cn/59/64/5964aa21364538867960524617ff8b86_1289x534.png)
##### 3.2 数组空指针异常
~~~
数组操作的常见问题二:
空指针异常
1.问题描述: java中使用java.lang.NullPointerException类来描述空指针异常
2.产生原因:
null是引用类型的空常量,可以赋值给任意引用类型的变量,一旦把null赋值给引用类型变量后,
说明该变量不再指向堆内存中的任何空间,也就不能操作堆内存空间的内容
null是引用类型的空常量,一旦把null赋值给数组变量后,
说明该数组变量不再指向堆内存空间中的任何数组,
也就不能再访问数组元素了,只要访问就会报出空指针异常
3.解决方案:
(1)找到引用变量是null的地方,进行修改,不让它是null,让它指向堆内存中的一个具体的数组
(2)不使用值为null的引用变量访问堆内存空间的内容
~~~
~~~
public class Demo02ArrayProblem {
public static void main(String[] args) {
//创建int数组one,并初始化
int[] one = new int[]{100, 200};//100编号是0,200的编号是1
System.out.println(one);//地址值: [I@1540e19d
System.out.println(one[0]);//100
System.out.println(one[1]);//200
one = null;
System.out.println(one);//null
//System.out.println(one[0]);//one的值是null,不能访问数组元素: 报出空指针异常
System.out.println("main...end...");
}
}
~~~
##### 图解:
![](https://img.kancloud.cn/ba/ed/baeda9bd2a76ad1b30a49b33765aa82a_1293x531.png)
### 第四章 数组练习【重点】
##### 4.1 数组遍历
~~~
数组遍历:
就是将数组中的每个元素分别获取出来,就是遍历。遍历也是数组操作中的基石。
public class Demo01ArrayEach {
public static void main(String[] args) {
//创建int数组array,并初始化
int[] array = {100, 200, 300};
System.out.println(array);//地址值
System.out.println(array[0]);//100
System.out.println(array[1]);//200
System.out.println(array[2]);//300
System.out.println("----------------");
//以上三行代码重复,只有作为索引编号的数字0,1,2是不同的,可以使用for循环获取作为索引编号的数字0,1,2
for (int i = 0; i < 3; i++) {
//System.out.println("索引编号: "+i+" 对应数组的元素值: "+array[i]);
System.out.println(array[i]);
}
System.out.println("----------------");
//以上for循环,数字3写死了,其实数字3可以使用数组长度(数组名称.length)代替
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
System.out.println("----------------");
for (int i = 0; i <= array.length - 1; i++) {
System.out.println(array[i]);
}
}
}
~~~
##### 4.2 求三个int数字的最大值
~~~
需求:
求三个int数字的最大值
实现步骤:
1.定义三个int变量a,b,c,并分别初始化
2.假设变量a的值是最大的,保存到int变量max中
3.判断如果b的值 大于 max,说明max中已经不是最大的
3.1 把b的值赋值给max
4.判断如果c的值 大于 max,说明max中已经不是最大的
4.1 把c的值赋值给max
5.打印max的值
public class Demo02VarMax {
public static void main(String[] args) {
//1.定义三个int变量a,b,c,并分别初始化
int a = 100, b = 200, c = 300;
//2.假设变量a的值是最大的,保存到int变量max中
int max = a;
//3.判断如果b的值 大于 max,说明max中已经不是最大的
if(b > max) {
//3.1 把b的值赋值给max
max = b;
}
//4.判断如果c的值 大于 max,说明max中已经不是最大的
if (c > max) {
//4.1 把c的值赋值给max
max = c;
}
//5.打印max的值
System.out.println("最大值: "+max);
}
}
~~~
图解:
![](https://img.kancloud.cn/78/4f/784ffc47e836ca039a6289fc0a376563_1098x466.png)
##### 4.3 数组获取最大值元素
~~~
需求:
求int数组元素最大值
实现步骤:
1.创建int数组array,并初始化
2.假设索引为0的元素是最大的,保存到int变量max中
3.使用for循环依次获取后面的(从索引1开始)每个元素
3.1如果当前元素值 大于 max 说明max中已经不是最大的了
3.2把当前元素赋值给max
4.for循环结束,打印max
~~~
~~~
public class Demo03ArrayMax {
public static void main(String[] args) {
//1.创建int数组array,并初始化
int[] array = {5, 15, 2000, 10000, 100, 4000};
//2.假设索引为0的元素是最大的,保存到int变量max中
int max = array[0];
//3.使用for循环依次获取后面的(从索引1开始)每个元素
for (int i = 1; i < array.length; i++) {
//3.1如果当前元素值 大于 max 说明max中已经不是最大的了
if(array[i] > max) {
//3.2把当前元素赋值给max
max = array[i];
}
}
//4.for循环结束,打印max
System.out.println("数组元素最大值: "+max);
}
}
~~~
##### 图解分析:
![](https://img.kancloud.cn/b0/63/b0632d0d81c261b65d00ef5bbb02a93e_1284x521.png)
##### 执行流程:
![](https://img.kancloud.cn/22/c4/22c4f3f4a7032d12bb3c14cb9714e96e_1242x465.png)
##### 总结
~~~
能够知道数组变量的定义格式
int[] array;
int array2[];
能够使用两种方式完成数组元素的初始化
1.动态初始化: 指定数组长度
int[] array = new int[3]
2.标准格式静态初始化: 指定元素
int[] array = new int[]{10,20,30};
3.简化格式静态初始化: 指定元素
int[] array = {10,20,30};
能够知道数组在内存中的初始化过程(了解)
能够完成数组的遍历操作
int[] array = {10,20,30};
for(int i = 0;i < array.length;i++) {
sout(array[i]);
}
for(int i = 0;i <= array.length-1;i++) {
sout(array[i]);
}
能够完成数组的获取最值操作
~~~