一、数组的概述和静态初始化
1. 数组
⭐数组是一种容器,可以用来存储同种数据类型的多个值
① 数组容器在存储数据的时候,需要结合隐式转换考虑
② 例如:int类型的数组容器(byte short int)
③ 例如:double类型的数组容器(byte short int long float double)
④ 建议:容器的类型,和存储的数据类型保持一致
2. 定义
① 数据类型[] 数组名
int [] array
② 数据类型 数组名[]
int array[]
3. 数组的静态初始化
① 初始化:就是在内存中,为数组开辟空间,并将数据存入容器的过程
② 完整格式:数据类型[] 数组名 = new 数据类型[] {元素1, 元素2, 元素3……}
③ 范例:int[] array = new int[]{11, 22, 33};
④ 范例:double[] array2 = new double[]{11.1, 22.2, 33.3};
⑤ 简化格式:数据类型[] 数组名 = {元素1, 元素2, 元素3……}
4. 样例
package com.itheima.arraydemo; public class ArrayDemo1{ public static void main(String[] args){ //格式: //静态初始化 //完整格式: //数据类型[]数组名 = new 数据类型[]{元素1, 元素2……} //简化格式: //数据类型[]数组名 = {元素1, 元素2……} //需求1:定义数组存储5个学生的年龄 int[] arr1 = new int[]{11,12,13,14,15}; int[] arr2 = {11,12,13,14}; //需求2:定义数组存储3个学生的姓名 String[] arr3 = new String[]{"zhangsan","lisi","wangwu"}; String[] arr4 = {"zhangsan","lisi","wangwu"}; //需求3:定义数组存储4个学生的身高 double[] arr5 = double[]{1.93,1.75,1.73,1.81}; double[] arr6 = {1.93,1.75,1.73,1.81}; } }
二、数组的地址值和元素访问
1. 数组的地址值
intp[] arr = {1,2,3,4,5}; System.out.println(arr);//[I@6d03e736 地址值
package com.itheima.arraydemo; public class ArrayDemo1{ public static void main(String[] args){ //格式: //静态初始化 //完整格式: //数据类型[]数组名 = new 数据类型[]{元素1, 元素2……} //简化格式: //数据类型[]数组名 = {元素1, 元素2……} //需求1:定义数组存储5个学生的年龄 /* int[] arr1 = new int[]{11,12,13,14,15}; int[] arr2 = {11,12,13,14}; //需求2:定义数组存储3个学生的姓名 String[] arr3 = new String[]{"zhangsan","lisi","wangwu"}; String[] arr4 = {"zhangsan","lisi","wangwu"}; //需求3:定义数组存储4个学生的身高 double[] arr5 = double[]{1.93,1.75,1.73,1.81}; */ double[] arr6 = {1.93,1.75,1.73,1.81}; System.out.println(arr6);//[D@776ec8df //扩展: //解释一下地址值的格式含义 //[:表示当前是一个数组 //D:表示当前数组里面的元素都是double类型的 //@:表示一个间隔符号(固定格式) //776ec8df:才是数组真正的地址值(十六进制) //平时我们习惯性的会把这个整体叫做数组的地址值 } }
2. 数组元素的访问
① 格式:数组名[索引]
② 索引:也叫做下标,从零开始,不间断
③ 样例
package com.itheima.arraydemo; public class ArrayDemo2{ public static void main(String[] args){ //利用索引对数组中的元素进行访问 //1.获取数组里面的元素 // 格式:数组名[索引] int[] arr = {1,2,3,4,5}; //获取数组中的第一个元素 //其实就是0索引上对应的元素 //int number = arr[0]; //System.out.println(number);//1 //获取数组中1索引上对应的数据,并直接打印出来 //System.out.println(arr[1]);//2 //2.把数据存储到数组当中 //格式:数组名[索引] = 具体数据/变量 //细节:一旦覆盖之后,原来的数据就不存在了 arr[0] = 100; System.out.println(arr[0]);//100 } }
三、数组的遍历和三道综合练习
1. 数组遍历
① 定义:将数组中所有的内容取出来,取出来之后可以(打印,求和,判断)
② 注意:遍历指的是取出数据的过程,不要局限的理解为,遍历就是打印!
2. 样例
package com.itheima.arraydemo; public class ArrayDemo3{ public static void main(String[] args){ //1.定义数组 int[] arr = {1,2,3,4,5}; //2.获取数组里面所有的元素 //格式:数组名[索引] /* System.out.println(arr[0]); System.out.println(arr[1]); System.out.println(arr[2]); System.out.println(arr[3]); System.out.println(arr[4]); */ //利用循环改进代码 //开始条件:0 //结束条件:数组的长度 - 1(最大索引) /* for(int i = 0; i < 5; i++){ //i:0 1 2 3 4 System.out.println(arr[i]); } */ //在Java中,关于数组的一个长度属性,length //调用方式:数组名.length //System.out.println(arr.length); for(int i = 0; i < arr.length; i++){ //i:0 1 2 3 4 System.out.println(arr[i]); } } }
3. 练习
package com.itheima.test; public class ArrTest1{ public static void main(String[] args){ /* 定义一个数组,存储1,2,3,4,5 遍历数组得到每一个元素,求数组里面所有的数据和 */ //分析: //1.定义一个数组,并添加数据1,2,3,4,5 int[] arr = {1,2,3,4,5}; //求和变量 int sum = 0; //2.遍历数组得到每一个数据,累加求和 for(int i = 0; i < arr.length;i++){ //i 依次表示数组里面的每一个索引 //arr[i] 依次表示数组里面的每一个元素 sum = sum + arr[i]; } //当循环结束之后,sum的值就是累加之后的结果 System.out.println(sum); } }
package com.itheima.test; public class ArrTest2{ public static void main(String[] args){ /* 定义一个数组,存储1,2,3,4,5,6,7,8,9,10 遍历数组得到每一个元素,统计数组里面一共有多少个能被3整除的数字 */ //分析: //定义一个数组 存储1,2,3,4,5,6,7,8,910 int[] arr = {1,2,3,4,5,6,7,8,9,10}; //定义一个变量,用来统计个数 int count = 0; //2.遍历数组得到每一个元素 for(int i = 0; i < arr.length;i++){ //i 表示数组里面每一个索引 //arr[i] 表示数组里面的每一个元素 //3.判断当前的元素是否为3的倍数,如果是那么统计变量就需要自增一次 if(arr[i] % 3 == 0){ //System.out.println(arr[i]); count++; } } //当循环结束之后,就表示数组里面所有的数字都判断完毕了,直接打印count即可 System.out.println("数组中能被3整除的数字有"+count+"个"); } }
package com.itheima.test; public class ArrTest3{ public static void main(String[] args){ /* 定义一个数组,存储1,2,3,4,5,6,7,8,9,10 遍历数组得到每一个元素 要求: 1.如果是奇数,则当前数字扩大两倍 2.如果是偶数,则当前数字变成二分之一 */ //分析: //1.定义一个数组,存1,2,3,4,5,6,7,8,9,10 int[] arr = {1,2,3,4,5,6,7,8,9,10}; //2.遍历数组得到每一个元素 for(int i = 0; i < arr.length; i++){ //i 依次表示数组里面的每一个索引 //arr[i] 依次表示数组里面的每一个元素 //3.对每一个元素进行判断 if(arr[i] % 2 == 0){ //偶数 变成二分之一 arr[i] = arr[i] / 2; }else{ //奇数 扩大两倍 arr[i] = arr[i] * 2; } } //遍历数组 //一个循环尽量只做一件事情 for(int i = 0; i < arr.length; i++){ System.out.println(arr[i]); } } }
四、数组的动态初始化和常见问题
1. 数组动态初始化
① 动态初始化:初始化时只指定数组长度,由系统为数组分配初始值
② 格式:数据类型[] 数组名 = new 数据类型[数组长度];
③ 范例:int[] arr = new int[3];
④ 样例
package com.itheima.arraydemo; public class ArrayDemo4{ public static void main(String[] args){ /* 定义一个数组,用来存班级中50个学生的姓名 姓名未知,等学生报道后,再进行添加 */ //格式: //数据类型[] 数组名 = new 数据类型[数组长度]; //再创建的时候,由我们自己指定数组的长度,由虚拟机给出默认的初始化值 String[] arr = new String[50]; //添加学生 arr[0] = "zhangsan"; arr[1] = "lisi"; //获取 System.out.println(arr[0]);//zhangsan System.out.println(arr[1]);//lisi System.out.println(arr[2]);//打印出来的是默认初始化值 //数组默认初始化值的规律 //整数类型:默认初始化值0 //小数类型:默认初始化值0.0 //字符类型:默认初始化值'/u0000' 空格 //布尔类型:默认初始化值 false //引用数据类型:默认初始化值 null int [] arr2 = new int[3]; System.out.println(arr[0]);//0 System.out.println(arr[1]);//0 System.out.println(arr[2]);//0 } }
2. 数组动态初始化和静态初始化的区别
① 动态初始化:手动指定数组的长度,由系统给出默认初始化值
只明确元素的个数,不明确具体数值,推荐使用动态初始化
② 静态初始化:手动指定数组元素,系统会根据元素个数,计算出数组的长度
需求中已经明确了要操作的具体数据,直接静态初始化即可
3. 数组常见问题
① 当访问了数组中不存在的索引,就会引发索引越界异常
② 样例
package com.itheima.arraydemo; public class ArrayDemo4{ public static void main(String[] args){ //1.定义一共数组 int[] arr = {1,2,3,4,5}; //长度:5 //最小索引:0 //最大索引:4(数组的长度 - 1) System.out.println(arr[2]); //小结: //索引越界异常 //原因:访问了不存在的索引 //避免:索引的范围 //最小索引:0 //最大索引:4(数组的长度 - 1) } }
五、数组练习1-求最值
package com.itheima.test; public class ArrTest4{ public static void main(String[] args){ //定义数组求最大值:33,5,22,44,55 //扩展问题: //1.根据求最大值问题的思路,自己改写一下求最小值 //2.为什么max要记录为arr[0],默认值不能为0吗 //不能写0 //max的初始化值一定要是数组中的值 //3.循环中开始条件一定是0吗 //循环的开始条件如果为0,那么第一次循环的时候是自己跟自己比了一下,对结果没有任何影响,但是效率偏低 //为了提高效率,减少一次循环的次数,循环开始条件可以写1 //1.定义数组用来存储5个值 int[] arr = {33,5,22,44,55}; //2.定义一个变量max用来存储最大值 //临时认为0索引的数据是最大的 int max = arr[0]; //3.循环获取数组中的每一个元素 //拿着每一个元素跟max进行比较 for(int i = 0; i < arr.length; i++){ //i 索引 arr[i] 元素 if(arr[i] > max){ max = arr[i]; } } //当循环结束之后,max记录的就是数组中的最大值 System.out.println(max);//55 } }
六、数组练习2-求和并统计个数
package com.itheima.test; public class ArrTest5{ public static void main(String[] args){ /* 需求:生成10个1~100之间的随机数存入数组 1) 求出所有数据的和 2) 求所有数据的平均数 3) 统计有多少个数据比平均值小 */ //分析: //1.定义数组 int[] arr = new int[10]; //2.把随机数存入到数组当中 Random r = new Random(); for(int i = 0; i < arr.length; i++){ //每循环一次,就会生成一个新的随机数 int number = r.nextInt(100) + 1; //把生成的随机数添加到数组当中 //数组名[索引] =数据 arr[i] = number; } //遍历数组 for(int i = 0; i < arr.length; i++){ System.out.println(arr[i]); } // 1) 求出所有数据的和 //定义求和变量 int sum = 0; for(int i = 0; i < arr.length; i++){ //循环得到每一个元素 //并把元素累加到sum当中 sum = sum + arr[i]; } System.out.println("数组中所有数据的和为:"+sum); // 2) 求所有数据的平均值 int avg = sum / arr.length; System.out.println("数组中平均数为:"+avg); // 3) 统计有多少个数据比平均值小 int count = 0; for(int i = 0; i < arr.length; i++){ if(arr[i] < avg){ count++; } } //当循环结束之后,就表示我已经找到了所有比平均数小的数据 System.out.println("在数组中,一共有"+count+"个数据,比平均数小"); //遍历数组,验证答案 for(int i = 0; i < arr.length; i++){ System.out.println(arr[i] + " "); } } }
七、数组练习3-交换数据
package com.itheima.test; public class ArrTest6{ public static void main(String[] args){ /* 需求:定义两个变量,交换两个变量记录的值 */ int a = 10; int b = 20; /* //把变量b的值,赋值给了变量a,那么变量a原来的值就被覆盖了 a = b;//a = 20 b =20 //把变量a的值,赋值给了b b = a;//a = 20 b =20 //System.out.println(a);//20 */ //定义一共临时的第三方变量 //把变量a的值,赋值给了temp int temp = a; //把变量b的值,赋值给了a,那么变量a原来记录的值就被覆盖了 a = b; //就是把变量a原来的值赋值给了变量b b = temp; system.out.println(a);//20 system.out.println(b);//10 } }
package com.itheima.test; public class ArrTest7{ public static void main(String[] args){ /* 需求:定义一个数组,将数组中0索引和最大索引处的值进行交换 */ //1.定义一个数组 int[] arr = {1,2,3,4,5}; //2.将数组中0索引和最大索引处的值进行交换 //也是可以利用第三方变量进行交换 int temp = arr[0]; arr[0] = arr[4]; arr[4] = temp; //3.遍历数组 for(int i = 0; i < arr.length; i++){ System.out.println(arr[i] + " "); } } }
package com.itheima.test; public class ArrTest8{ public static void main(String[] args){ /* 需求: 定义一个数组,存入1,2,3,4,5,交换首尾索引对应的元素 交换前:1,2,3,4,5 交换后:5,4,3,2,1 */ //1.定义数组存储数据 int[] arr = {1,2,3,4,5}; //2.利用循环去交换数据 for(int i = 0,j = arr.length - 1; i < j; i++,j--){ //交换变量i和变量j指向的元素 int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } //当循环结束之后,那么数组中的数据就实现了头尾交换 for(int i = 0; i < arr.length; i++){ System.out.println(arr[i] + " "); } } }
八、数组练习4-打乱数据
package com.itheima.test; public class ArrTest9{ public static void main(String[] args){ //需求:定义一个数组,存入1~5,要求打乱数组中所有数据的顺序 //难点: //如何获取数组中的随机索引 /* int[] arr = {1,2,3,4,5}; //索引范围:0 1 2 3 4 Random r = new Random(); int randomIndex = r.nextInt(arr.length); System.out.println(randomIndex); */ //1.定义数组存储1~5 int[] arr = {1,2,3,4,5}; Random r = new Random(); for(int i = 0; i < arr.length; i++){ //生成一个随机索引 int randomIndex = r.nextInt(arr.length); //拿着随机索引指向的元素跟i指向的元素进行交换 int temp = arr[i]; arr[i] = arr[randomIndex]; arr[randomIndex] = temp; } //当循环结束之后,那么数组中所有的数据已经打乱顺序了 for(int i = 0; i < arr.length; i++){ System.out.println(arr[i] + " "); } } }
九、数组的内存图
1. Java的内存分配
① 栈:方法运行时使用的内存,比如main方法运行,进入方法栈中执行
② 堆:存储对象或者数组,new来创建的,都存储在堆内存
③ 方法区:存储可以运行的class文件
④ 本地方法栈:JVM在使用操作系统功能的时候使用,和我们开发无关
⑤ 寄存器:给CPU使用,和我们开发无关
注意:
从JDK8开始,取消方法区,新增元空间。把原来方法区的多种功能进行拆分,有的功能放到了堆中,有的功能放到了元空间中。
2. 数组的内存图
① 只要new出来的一定是在堆里面开辟了一个小空间
② 如果new了多次,那么在堆里面有多个小空间,每个小空间中都有各自的数据
3. 两个数组指向同一个空间的内存图
当两个数组指向同一个小空间时,其中一个数组对小空间中的值发生了改变,那么其他数组再次访问的时候都是修改之后的结果了