目录
JAVA数组的基础入门
什么是数组,什么情况下使用数组
- 数组是一个存储多个相同类型数据的容器
- 当需要将大量相同数据类型存储起来并且不需要怎么进行增删数据时
数组的创建方式
- 静态创建方式(当数组创建时就已经有了值)
int[] arr1 = {1,3,5,6}; int[] arr2 = new int[]{1,3,5,6,8,1};
- 动态创建方式(创建时只指定长度并分配默认值),默认值就是每个数据类型的默认值
int[] arr3 = new[10];
获取数组的数据
// 数组的每一个元素都会有一个对应的索引(下标),索引从0开始 int[] arr4 = {1,3,5,6};// 这其中索引从0开始,也就是其中的1的索引为0,3的索引为1,以此类推 // 那么要获取到其中的数字6 System.out.println(arr4[3]);
数组的内存模型
// 栈中的main函数在执行到该条语句时 /* 1、会创建一个int数组对象,放在堆内存中。(其对象的值是一片连续的区域,每一个索引位置都对应着一个内存地址)理解为对象是一个地址,其中的元素也有对应的内存地址 2、栈内存中会创建一个数据类型为 int[],并且名称为arr5的引用,然后用该引用指向堆内存中的刚刚创建的对象的内存地址 */ int[] arr5 = {3,4,5,6};
为什么数组查询修改快,而增删慢?
查询快的原因
- 因为数组拥有索引,而每个索引所对应的数据都会有一个内存地址
- 每次使用索引查找数据时,都会经过一个算法 (第一个索引的内存地址 + 当前索引 * 数据大小)来快速定位到当前索引所指向的内存地址,所以查询很快
增删慢的原因
- 增删慢是因为数组是一片连续的区域,按理来说数组创建后长度就是固定的,所以增加与删除数组实际上都是创建一个新的数组
- 而创建了一个新的数组后还要将数组进行重新的数据编排以此来完成数据的增删操作,所以速度慢
数组的两种遍历方式以及区别
fori的遍历方式
int[] arr6 = {8,9,5,4,7,3,1}; for(int i = 0; i < arr6.length; i++) { System.out.println("arr6[" + i + "] = " + arr6[i]); }
数组获取极值及其索引
/* 要求,1、从键盘输入一段数组,期间中空格隔开 2、要求输出最大值以及最大值的索引位置 提示:不用键盘输入,直接定义一个数组也是可以的。 */ try (Scanner scanner = new Scanner(System.in)) { String[] strings = scanner.nextLine().split(" "); // 将String[]转换为int[] int[] arrs = Arrays.stream(strings).mapToInt(Integer::valueOf).toArray(); // 上面的两行代码如果不熟悉的话可以直接定义一个数组。例如: int[] arrs = {1,3,5,12,33,12,15,46}; // 获取数组最大值 int max = arrs[0]; int index = 0; for (int i = 0; i < arrs.length; i++) { if(max < arrs[i]) { max = arrs[i]; index = i; } } System.out.println("最大值为" + max + " 在数组中的位置为:" + index); }
增强foreach的遍历方式
int[] arr6 = {8,9,5,4,7,3,1}; for(int item : arr6) { System.out.println(item); }
两种遍历方式区别
- fori有索引位置,foreach没有
- fori遍历出来的每个元素都指向内存地址,foreach遍历出来的每个元素都是一个临时存储局部变量
- 按照第二条所得结论,fori遍历时可以修改数组中的元素,而foreach不可以在遍历时修改数组的元素
JAVA数组的基础入门
什么是数组,什么情况下使用数组
- 数组是一个存储多个相同类型数据的容器
- 当需要将大量相同数据类型存储起来并且不需要怎么进行增删数据时
数组的创建方式
- 静态创建方式(当数组创建时就已经有了值)
int[] arr1 = {1,3,5,6}; int[] arr2 = new int[]{1,3,5,6,8,1};
- 动态创建方式(创建时只指定长度并分配默认值),默认值就是每个数据类型的默认值
int[] arr3 = new[10];
获取数组的数据
// 数组的每一个元素都会有一个对应的索引(下标),索引从0开始 int[] arr4 = {1,3,5,6};// 这其中索引从0开始,也就是其中的1的索引为0,3的索引为1,以此类推 // 那么要获取到其中的数字6 System.out.println(arr4[3]);
数组的内存模型
// 栈中的main函数在执行到该条语句时 /* 1、会创建一个int数组对象,放在堆内存中。(其对象的值是一片连续的区域,每一个索引位置都对应着一个内存地址)理解为对象是一个地址,其中的元素也有对应的内存地址 2、栈内存中会创建一个数据类型为 int[],并且名称为arr5的引用,然后用该引用指向堆内存中的刚刚创建的对象的内存地址 */ int[] arr5 = {3,4,5,6};
为什么数组查询修改快,而增删慢?
查询快的原因
- 因为数组拥有索引,而每个索引所对应的数据都会有一个内存地址
- 每次使用索引查找数据时,都会经过一个算法 (第一个索引的内存地址 + 当前索引 * 数据大小)来快速定位到当前索引所指向的内存地址,所以查询很快
增删慢的原因
- 增删慢是因为数组是一片连续的区域,按理来说数组创建后长度就是固定的,所以增加与删除数组实际上都是创建一个新的数组
- 而创建了一个新的数组后还要将数组进行重新的数据编排以此来完成数据的增删操作,所以速度慢
数组的两种遍历方式以及区别
fori的遍历方式
int[] arr6 = {8,9,5,4,7,3,1}; for(int i = 0; i < arr6.length; i++) { System.out.println("arr6[" + i + "] = " + arr6[i]); }
增强foreach的遍历方式
int[] arr6 = {8,9,5,4,7,3,1}; for(int item : arr6) { System.out.println(item); }
两种遍历方式区别
- fori有索引位置,foreach没有
- fori遍历出来的每个元素都指向内存地址,foreach遍历出来的每个元素都是一个临时存储局部变量
- 按照第二条所得结论,fori遍历时可以修改数组中的元素,而foreach不可以在遍历时修改数组的元素
数组的小练习,获取极值及索引、数组的扩容及缩容
获取极值及其索引
/* 要求,1、从键盘输入一段数组,期间中空格隔开 2、要求输出最大值以及最大值的索引位置 提示:不用键盘输入,直接定义一个数组也是可以的。 */ try (Scanner scanner = new Scanner(System.in)) { String[] strings = scanner.nextLine().split(" "); // 将String[]转换为int[] int[] arrs = Arrays.stream(strings).mapToInt(Integer::valueOf).toArray(); // 上面的两行代码如果不熟悉的话可以直接定义一个数组。例如: int[] arrs = {1,3,5,12,33,12,15,46}; // 获取数组最大值 int max = arrs[0]; int index = 0; for (int i = 0; i < arrs.length; i++) { if(max < arrs[i]) { max = arrs[i]; index = i; } } System.out.println("最大值为" + max + " 在数组中的位置为:" + index); }
在数组指定索引位置插入数据
// 方式1 public static int[] insertArrayElementByIndex(int[] arr, int index, int element) { // 先动态创建一个数组 int[] newArr = new int[arr.length + 1]; // 遍历原数组,获取索引前的数据 for (int i = 0; i < index; i++) { newArr[i] = arr[i]; } // 将索引处的值赋值 newArr[index] = element; // 遍历索引后的数据 for (int i = index; i < arr.length; i++) { newArr[i + 1] = arr[i]; } return newArr; } // 方式2 public static int[] insertArrayElementByIndex2(int[] arr, int index, int element) { // 先动态创建一个数组 int[] newArr = new int[arr.length + 1]; // 遍历原数组,获取索引前的数据 System.arraycopy(arr, 0, newArr, 0, index); // 将索引处的值赋值 newArr[index] = element; // 遍历索引后的数据 System.arraycopy(arr, index, newArr, index + 1, arr.length - index); return newArr; }
删除数组指定位置数据
// 方式1 public static int[] deleteArrayElementByIndex(int[] arr, int index) { // 先动态创建一个数组 int[] newArr = new int[arr.length - 1]; // 遍历原数组,获取索引前的数据 for (int i = 0; i < index; i++) { newArr[i] = arr[i]; } // 遍历索引后的数据,由于长度减少了,所以需要少遍历一次给新数组赋值 for (int i = index; i < arr.length - 1; i++) { newArr[i] = arr[i + 1]; } return newArr; } // 方式2 public static int[] deleteArrayElementByIndex2(int[] arr, int index) { // 先动态创建一个数组 int[] newArr = new int[arr.length - 1]; // 遍历原数组,获取索引前的数据 System.arraycopy(arr, 0, newArr, 0 , index); // 遍历索引后的数据,由于长度减少了,所以需要少遍历一次给新数组赋值 System.arraycopy(arr, index + 1, newArr, index , arr.length - 1 - index); return newArr; }
Arrays工具类的使用以及System.arraycopy()方法的使用
Arrays工具类
Integer[] arr = {3, 5, 6, 1, 2, 5, 7}; // 倒叙排序数组 Arrays.sort(arr, Collections.reverseOrder()); // 升序排序数组 Arrays.sort(arr); // 复制数组 Integer[] copyArr = Arrays.copyOf(arr, arr.length); // 将数组转换为一串字符串 String arrStr = Arrays.toString(copyArr); // 输出结果为:[1, 2, 3, 5, 5, 6, 7] System.out.println(arrStr); // 使用二分查找法查找某个数据所在的索引位置 int index = Arrays.binarySearch(arr, 5); System.out.println(index);
System.arraycopy()方法的使用
// System.arraycope()方法 复制整个数组 /* 参数解析 * Object src: 原始数组 * int srcPos: 从原始数组的第几个下标开始复制 * Object dest: 目标数组,也就是要复制到该数组中 * int destPos: 从目标数组的第几个下标开始复制 * int length: 一共需要复制几个元素 * 提示一点:源数组与目标数组必须为相同类型的数组 */ int[] arr = {3,5,6,1,2,5,7}; int[] newArr = new int[arr.length]; System.arraycopy(arr, 0, newArr, 0, arr.length); System.out.println(Arrays.toString(newArr));
综合案例练习
/* 1、键盘输入 [学生姓名 学生成绩]后按回车,可以无限的录入学生信息 2、当输入over按回车时停止键盘输入 3、输出学生的名次、姓名、成绩 */ public class Test4 { public static void main(String[] args) { Student[] stuArr = new Student[0]; Scanner scanner = new Scanner(System.in); // 输入学生信息,格式为: 学生姓名 成绩;使用标记over结束 while (true) { String str = scanner.nextLine(); if ("over".equals(str)) { break; } String[] s = str.split(" "); Student student = new Student(s[0], Integer.parseInt(s[1])); // 插入一个数据 stuArr = insertArrElement(stuArr, student); } Arrays.sort(stuArr, ((o1, o2) -> Integer.compare(o2.getScore(), o1.getScore()))); for (int i = 0; i < stuArr.length; i++) { System.out.println("比赛名次为第" + (i + 1) + "名 姓名为:" + stuArr[i].getName() + " 成绩为:" + stuArr[i].getScore()); } } private static Student[] insertArrElement(Student[] stuArr, Student student) { // 复制前面的所有内容,用这一行可以 //Student[] newArr = Arrays.copyOf(stuArr, stuArr.length + 1); // 用这下面两行也可以做到 Student[] newArr = new Student[stuArr.length + 1]; System.arraycopy(stuArr, 0, newArr, 0, stuArr.length); // 将最后一位添加上 newArr[newArr.length - 1] = student; return newArr; } } class Student { private String name; private int score; public Student(String name, int score) { this.name = name; this.score = score; } public String getName() { return name; } public int getScore() { return score; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", score=" + score + '}'; } }
运行效果如下