数组习题的引入
import java.util.*; public class TestArray01{ public static void main(String[] args){ //功能:键盘录入十个学生的成绩,求和,求平均数 //定义一个求和的变量 int sum = 0; Scanner sc = new Scanner(System.in); for(int i = 1;i<=10;i++){//i:控制循环的次数 System.out.println("请录入第"+i+"个学生的成绩"); int score = sc.nextInt(); sum += score; } System.out.println("十个学生的成绩之和为:"+sum); System.out.println("十个学生的成绩平均数为:"+sum/10); //缺点:求某个学生的成绩? -----》不能 } }
缺点:不能求每个学生的具体成绩是多少
解决:将成绩进行存储 -----》引入:数组
感受到数组的作用:数组用来存储数据的,在程序设计中,为了方便处理,数组用来将相同类型的若干数据组织起来。这个若干数据的集合我们称之为:数组。
1.数组的学习
【1】数组的定义
数组是相同类型的数据的有序集合。数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。其中,每个数据称作一个元素,每个元素可以通过一个索引(下标)来访问他们。
数组的四个基本特点:
(1)长度是确定的。数组一旦被创建,它的大小就是不可以改变的。
(2)其元素的类型必须是相同类型,不允许出现混合类型。
(3)数组的类型可以是任何数据类型,包括基本类型和引用类型。
(4)数组有索引的:索引从0开始,到数组 length-1 结束
(5)数组变量属于引用类型,数组也是对象
ps:数组变量属于引用类型,数组也是对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,java中对象是在堆中的,因此数据无论保存原始类型还是其他对象类型,数据对象本身是在堆中存储的。
【2】数组的学习
public class TestArray02{ public static void main(String[] args){ //数组的作用:用来存储相同类型的数据 //以int类型的数据为案例:数组用来存储int类型的数据 //1.声明(定义数组) int[] arr;//定义一个int类型的数组,名字叫arr int arr2[]; //如果数组只声明,没有后续操作,那么这个数组相当于没有定义 int arr3[] = null;// 空 辨别:数组赋值为null和什么都没有赋值,不一样的效果 //2.创建 arr = new int[4];//给数组开一个长度为4的空间 //编译期声明和创建会被合为一句话:int[] arr = new int[4]; //3.赋值 arr[0] = 11; arr[3] = 13; arr[2] = 44; arr[1] = 55; /* arr[4] = 77; 出现异常:Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4 Array 数组 Index 索引 OutOf 超出 Bounds 界限 Exception 异常 ----》数据索引越界异常 */ //4.使用 System.out.println(arr[2]); System.out.println(arr[0]+100); //通过一个数组属性来获取 length 长度 System.out.println("数组的长度是:"+arr.length); } }
(内存分析)
2.数组的遍历
import java.util.*; public class TestArray03{ public static void main(String[] args){ //功能:键盘录入十个学生的成绩,求和,求平均数 //定义一个int类型的数组,长度为10; int[] scores = new int[10]; //定义一个求和的变量 int sum = 0; Scanner sc = new Scanner(System.in); for(int i = 1;i<=10;i++){//i:控制循环的次数 System.out.println("请录入第"+i+"个学生的成绩"); int score = sc.nextInt(); scores[i-1] = score; sum += score; } System.out.println("十个学生的成绩之和为:"+sum); System.out.println("十个学生的成绩平均数为:"+sum/10); //求全部学生的成绩: //将数组中的每个元素进行查看 ---->数组的遍历: //方式一:普通for循环 -----》正向遍历 for(int i = 0;i<=9;i++){ System.out.println("第"+(i+1)+"个学生的成绩为"+scores[i]); } //方式二:增强for循环 //对 scores数组进行遍历,遍历出来的每一个元素都用int类型的num接收 for(int num:scores){ //每次都将num在控制台输出 System.out.println(num); } /* 增强for循环: 优点:代码简单 缺点:单纯的增强for循环不能设计和索引相关的操作 */ //方式三:利用普通for循环;逆向遍历 for(int i=9;i>=0;i--){ System.out.println("第"+(i+1)+"个学生的成绩为"+scores[i]); } } }
3.数组的初始化方式
【1】静态初始化
除了用new关键字来产生数组以外,还可以直接在定义数组的同时就为数组元素分配空间并赋值。
eg:
int[] arr = {12,23,45};
int[] arr = new int[] {12,23,45};
注意:
(1).new int[3]{12,23,45}; ----->错误(自动默认分配三个空间,不用写三个长度)
(2).int[] arr;
arr = {12,23,45} ------>错误 (这么写编译器不认为这是一个数组)
【2】动态初始化
数组定义与数组元素分配空间并复制的的操作分开进行。
eg:
int[] arr = new int[3];
arr[0] = 12;
arr[1] = 23;
arr[2] = 45;
【3】默认初始化
数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。
eg:
int[] arr = new int[3]; ----->数组有默认的初始化值
4.数组的应用
1)最值问题
【1】实现一个功能:给定一个数组int[] arr = {12,23,34,45,56,67,1,4}; 求出数组中的最大数 。
(原理:打擂原理)
public class TestArray04{ public static void main(String[] args){ //实现一个功能:给定一个数组int[] arr = {12,23,34,45,56,67,1,4} //1.给定一个数组 int[] arr = {12,23,34,45,56,67,1,4}; //2.求出数组中的最大值 //先找一个数上擂台,假定认为这个数最大 int maxNum = arr[0]; for(int i = 0;i<arr.length;i++){ if(arr[i]>maxNum){ maxNum = arr[i]; } } System.out.println("当前数组中最大的数为:"+maxNum); } }
【2】将求最大值的方法提取出来
public class TestArray05{ public static void main(String[] args){ //实现一个功能:给定一个数组int[] arr = {12,23,34,45,56,67,1,4} //1.给定一个数组 int[] arr = {12,23,34,45,56,67,1,4}; //2.求出数组中的最大值 //调用方法: int num = getMaxNum(arr); System.out.println("当前数组中最大的数为:"+num); } /* 想提取一个方法:求数组中的最大值 求哪个数组中的最大值 ----》不确定因素:哪个数组(形参) ---》返回值:最大值 */ public static int getMaxNum(int[] arr){ //先找一个数上擂台,假定认为这个数最大 int maxNum = arr[0]; for(int i = 0;i<arr.length;i++){ if(arr[i]>maxNum){ maxNum = arr[i]; } } return maxNum; } }
【3】画内存
方法的实参传递给形参的时候一定要注意:一切都是值传递
如果是基本数据类型,那么传递的就是字面值
如果是引用数据类型,那么传递的就是地址值
2)查询问题
【1】查询指定位置的元素
public class TestArray06{ public static void main(String[] args){ //查询指定位置的元素 //给定一个数组: int[] arr = {12,23,34,45,3,4,6}; //查找索引位置为2的元素的位置 System.out.println(arr[2]); } }
上面的代码体现了数组的一个优点:
在按照位置查询的时候,直接一步到位,效率非常高
【2】查找指定元素的位置 ------》找出元素对应的索引
public class TestArray07{ public static void main(String[] args){ //查找指定元素的位置 ---》找出元素对应的索引 //给定一个数组: int[] arr = {12,23,34,4,3,4554,34,3}; // 0 1 2 3 4 5 6 7 //功能:查询元素34对应的索引 int index = -1;//这个初始值只要不是数组的索引即可 for(int i=0;i<arr.length;i++){ if(arr[i]==34){ index = i;//只要找到了元素,那么index就变为i break;//只要找到了这个元素,循环停止 } } if(index!=-1){ System.out.println("元素对应位置的索引为"+index); }else{//index==-1 System.out.println("查无此数!"); } } }
【3】将查询指定元素对应的索引的功能提取为方法
public class TestArray08{ public static void main(String[] args){ //查找指定元素的位置 ---》找出元素对应的索引 //给定一个数组: int[] arr = {12,23,34,4,3,4554,34,3}; // 0 1 2 3 4 5 6 7 //功能:查询元素34对应的索引 //调用方法 int index = getIndex(arr,34); //后续对index的值进行一个判断 if(index!=-1){ System.out.println("元素对应位置的索引为"+index); }else{//index==-1 System.out.println("查无此数!"); } } /* 定义一个方法:查询数组中指定元素对应的索引; 不确定因素:哪个数组,那个指定元素 (形参) 返回值:索引 */ public static int getIndex(int[] arr,int ele){ int index = -1;//这个初始值只要不是数组的索引即可 for(int i=0;i<arr.length;i++){ if(arr[i]==ele){ index = i;//只要找到了元素,那么index就变为i break;//只要找到了这个元素,循环停止 } } return index; } }
3)添加元素
【1】实现一个功能:在数组下标为2的位置添加一个元素
添加逻辑:
public class TestArray09{ public static void main(String[] args){ //功能:给定一个数组,在数组下标为2的位置上添加一个元素55 //1.给定一个数组 int[] arr = {12,23,44,67,76,89,22,2,3,35,455,6}; // 0 1 2 3 4 5 6 7 8 9 10 11 //2.输出增加元素前的数组 System.out.print("增加元素前的数组:"); for(int i=0;i<arr.length;i++){ if(i!=arr.length-1){ System.out.print(arr[i]+","); }else{//i==arr.length-1 最后一个元素不用加逗号 System.out.print(arr[i]); } } //3.增加元素 /* arr[6] = arr[5]; arr[5] = arr[4]; arr[4] = arr[3]; arr[3] = arr[2]; arr[2] = 91; */ int index = 2;//在指定位置添加元素 for(int i=arr.length-1;i>=(index+1);i--){ arr[i] = arr[i-1]; } arr[index] = 91; //4.输出增加元素后的数组 System.out.print("\n增加元素后的数组:"); for(int i=0;i<arr.length;i++){ if(i!=arr.length-1){ System.out.print(arr[i]+","); }else{ System.out.print(arr[i]); } } } }
【2】将添加功能提取为一个方法
import java.util.*; public class TestArray10{ public static void main(String[] args){ //功能:给定一个数组,在数组下标为2的位置上添加一个元素55 //1.给定一个数组 int[] arr = {12,23,44,67,76,89,22,2,3,35,455,6}; // 0 1 2 3 4 5 6 7 8 9 10 11 //2.输出增加元素前的数组 System.out.print("增加元素前的数组:"); for(int i=0;i<arr.length;i++){ if(i!=arr.length-1){ System.out.print(arr[i]+","); }else{//i==arr.length-1 最后一个元素不用加逗号 System.out.print(arr[i]); } } //从键盘录入数据 Scanner sc = new Scanner(System.in); System.out.println("\n请录入你要添加元素的指定下标"); int index = sc.nextInt(); System.out.println("\n请录入你要添加的元素"); int ele = sc.nextInt(); //3.增加元素 /* arr[6] = arr[5]; arr[5] = arr[4]; arr[4] = arr[3]; arr[3] = arr[2]; arr[2] = 91; */ //调用方法 insertEle(arr,index,ele); //4.输出增加元素后的数组 System.out.print("\n增加元素后的数组:"); for(int i=0;i<arr.length;i++){ if(i!=arr.length-1){ System.out.print(arr[i]+","); }else{ System.out.print(arr[i]); } } } /* 提取一个添加元素的方法: 在数组的指定位置上添加一个指定的元素 在哪个数组的哪个位置添加哪个元素! (不确定因素:形参:哪个数组,哪个位置,哪个元素,) 返回值:无 */ public static void insertEle(int[] arr,int index,int ele){ for(int i=arr.length-1;i>=(index+1);i--){ arr[i] = arr[i-1]; } arr[index] = ele; } }
4)删除元素
逻辑
import java.util.*; public class TestArray11{ public static void main(String[] args){ //功能:给定一个数组,删除下标为2元素 //1.给定一个数组 int[] arr = {12,23,45,55,43}; // 0 1 2 3 4 //2.输出删除前的数组 System.out.println("删除元素前的数组为:"+Arrays.toString(arr)); //3.删除 /* arr[2] = arr[3]; arr[3] = arr[4]; arr[4] = arr[5]; */ int index = 0; for(int i=index;i<=arr.length-2;i++){ arr[i] = arr[i+1]; } arr[arr.length-1] = 0; //4.输出删除后的数组 System.out.println("删除元素后的数组为:"+Arrays.toString(arr)); } }
【2】实现一个功能:删除指定元素(位置未知)
import java.util.*; public class TestArray12{ public static void main(String[] args){ //功能:给定一个数组,删除指定元素 //1.给定一个数组 int[] arr = {12,23,45,55,43}; // 0 1 2 3 4 //2.输出删除前的数组 System.out.println("删除元素前的数组为:"+Arrays.toString(arr)); //找到要删除的元素对应的索引 int index = -1; for(int i=0;i<arr.length;i++){ if(arr[i]==12){ index = i; break; } } //3.删除 /* arr[2] = arr[3]; arr[3] = arr[4]; arr[4] = arr[5]; */ if(index!=-1){ for(int i=index;i<=arr.length-2;i++){ arr[i] = arr[i+1]; } arr[arr.length-1] = 0; }else{//index==-1 System.out.println("没有你要删除的元素"); } //4.输出删除后的数组 System.out.println("删除元素后的数组为:"+Arrays.toString(arr)); } }
5.详述main方法
【1】main方法:程序的入口。在同一个类中,如果有多个方法,虚拟机就会识别main方法从这个方法作为程序的入口
【2】main方法格式严格要求:
public static void main(String[] args){}
public static ------>修饰符(暂用)
void ----->代表方法没有返回值
main ----->见名知意名字
String[] args ----->形参 ----》不确定因素
【3】问题:程序中是否可以有其它的方法也叫main方法?
可以
public static void main(String[] args){ } public static void main(String str){ }
(方法名相同,形参列表不同,方法的重载)
【4】形参为String[],那么实参到底是什么?
public class TestArray13{ public static void main(String[] args){ //从侧面验证: //int[] arr1;----->对数组只声明,没有后续操作,相当于 白定义了 /* int[] arr2 = null; System.out.println(arr2.length); ----->Exception in thread "main" java.lang.NullPointerException */ /* int[] arr3 = new int[0]; System.out.println(arr3.length);----->输出为0 */ /* System.out.println(args.length); 这个结果证明,参数是String[],实参是 new String[0] 默认情况下,虚拟机在调用main方法的时候就是传入了一个长度为0的数组 */ System.out.println(args.length); for(String str:args){ System.out.println(str); } } }
手动传入实参:
有特殊符号可以加上"";没有特殊符号用空格隔开即可
6.可变参数(拓展)
public class TestArray14{ /* 1.可变参数:(作用)提供了一个方法,参数的个数是可变的 int...num double...num float...num boolean...num 作用:解决了部分方法的重载问题 2.可变参数在JDK1.5之后加入的新特性 3.方法的内部对可变参数的处理跟数组是一样的 4.可变参数和其他数据一起作为形参的时候,可变参数一定要放在最后 5.我们自己写代码,尽量不要使用可变参数 */ public static void main(String[] args){ //method01(1); //method01(); //method01(2,34,56); method01(23,34,45,67,87); //method01(new int[]{12,33,77,88,99}); } public static void method01(int num2,int...num){ System.out.println("----a"); for(int i:num){ System.out.print(i+"\t"); } System.out.println(); System.out.println(num2); } }
7.Arrays类
(为了方便我们对数组进行操作,系统提供了一个类Arrays,我们把它当成工具类来使用)
import java.util.*; public class TestArray15{ public static void main(String[] args){ //给定一个数组 int[] arr = {1,2,3,4,5,6}; //toString:对数组进行遍历查看,返回的是一个字符串,看的较为清楚 System.out.println(Arrays.toString(arr)); //binarySearch:二分法查找,找出指定数组中的指定元素对应的索引 //方法的使用是有前提的:一定要查看的是一个有序的数组 //sort:排序----->升序 Arrays.sort(arr); System.out.println(Arrays.toString(arr)); System.out.println(Arrays.binarySearch(arr,4)); int[] arr2 = {1,3,5,7,9}; //copyOf:完成数组的复制 int[] newArr = Arrays.copyOf(arr2,4); System.out.println(Arrays.toString(newArr)); //copyOfRange:区间复制: int[] newArr2 = Arrays.copyOfRange(arr2,1,4);//[1-4) --->1,2,3位置 System.out.println(Arrays.toString(newArr2)); //equals:比较两个数组的值是否一样 int[] arr3 = {1,3,5,7,0}; int[] arr4 = {1,3,5,7,0}; System.out.println(Arrays.equals(arr3,arr4));//true System.out.println(arr3==arr4);//false ==比较左右两侧的值是否相等,比较的是左右两侧地址的值,返回值结果一定是false //fill:数组的填充 int[] arr5 = {1,3,5,7,0}; Arrays.fill(arr5,10); System.out.println(Arrays.toString(arr5)); } }
拓展:(数组的复制)
static void | arraycopy(object src , int srcPos , object dest , int destPos , int length)
从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束
src --- 源数组
srcPos ---- 源数组中的起始位置
dest ----- 目标数组
destPos ---- 目标数组中的起始位置
length ---- 要复制的数组元素的数量
(代码插入)
import java.util.*; public class TestArray16{ public static void main(String[] args){ //给定一个源数组 int[] srcArr = {11,23,44,55,667,88,55,66,99}; //给定一个目标数组 int[] destArr = new int[10]; //复制 System.arraycopy(srcArr,1,destArr,3,3); //遍历查看目标数组: System.out.println(Arrays.toString(destArr)); } }
结果:
8.二维数组
【1】引入:本质上全部都是一维数组
【2】代码:
public class TestArray17{ public static void main(String[] args){ //定义一个二维数组 int[][] arr = new int[3][];//本质上定义了一个一维数组,长度为3 int[] a1 = {1,2,3}; arr[0] = a1; arr[1] = new int[]{4,5,6,7}; arr[2] = new int[]{8,9}; } }
对应的内存分析:
【3】四种遍历方式
public class TestArray17{ public static void main(String[] args){ //定义一个二维数组 int[][] arr = new int[3][];//本质上定义了一个一维数组,长度为3 int[] a1 = {1,2,3}; arr[0] = a1; arr[1] = new int[]{4,5,6,7}; arr[2] = new int[]{8,9}; //读取6这个元素 System.out.println(arr[1][2]); //对二维数组进行遍历 /* //方式1:外层普通for循环+内层普通for循环 for(int i=0;i<=2;i++){ for(int j=0;j<arr[i].length;j++){ System.out.print(arr[i][j]+"\t"); } System.out.println(); } //方式2:外层普通for循环+内层增强for循环: for(int i=0;i<=2;i++){ for(int num:arr[i]){ System.out.println(num+"\t"); } System.out.println(); } //方式3:外层增强for循环+内层增强for循环 for(int[] a:arr){ for(int num:a){ System.out.println(num+"\t"); } } */ //方式4:外层增强for循环+内层普通for循环 for(int[] a:arr){ for(int i=0;i<a.length;i++){ System.out.println(a[i]+"\t"); } System.out.println(); } } }