[JavaSE] 数组的定义和使用(二)
目录
数组练习
💬 数组转字符串
💬 数组拷贝
💬 找数组中的最大元素
💬 求数组中元素的平均值
💬 查找数组中指定元素(顺序查找)
💬 查找数组中指定元素(二分查找)
💬 感受二分查找的效率
疫情当前,大家要做好防护哦。
带好口罩了嘛?
那么大家跟着Nick来学习今天的数组知识!
数组练习
💬 数组转字符串
📝 代码示例
import java.util.Arrays int[] arr = {1,2,3,4,5,6}; String newArr = Arrays.toString(arr); System.out.println(newArr); // 执行结果 [1, 2, 3, 4, 5, 6]
🔴 使用这个方法后续打印数组就更方便一些
🔴 Java 中提供了 java.util.Arrays 包, 其中包含了一些操作数组的常用方法
⚫ 什么是包?
💠 例如做一碗油泼面, 需要先和面, 擀面, 扯出面条, 再烧水, 下锅煮熟, 放调料, 泼油。
💠 但是其中的 "和面, 擀面, 扯出面条" 环节难度比较大, 不是所有人都能很容易做好. 于是超市就提供了一些直接 已经扯好的面条, 可以直接买回来下锅煮. 从而降低了做油泼面的难度, 也提高了制作效率。
💠 程序开发也不是从零开始, 而是要站在巨人的肩膀上。
💠 像我们很多程序写的过程中不必把所有的细节都自己实现, 已经有大量的标准库(JDK提供好的代码)和海量的 第三方库(其他机构组织提供的代码)供我们直接使用. 这些代码就放在一个一个的 "包" 之中. 所谓的包就相当 于卖面条的超市. 只不过, 超市的面条只有寥寥几种, 而我们可以使用的 "包" , 有成千上万
📝 代码示例
🔴 这是Nick写了两个自己版本的数组转字符串
public class MyToString { public static void main(String[] args) { int[] arr={1,2,4,5,7}; System.out.println(printArray(arr)); } public static String printArray(int[] arr){ if (arr==null){ return null; } String str="["; for (int i = 0; i < arr.length; i++) { if(i==arr.length-1){ str+=arr[i]; }else{ str+=arr[i]+","; } } str+="]"; return str; } public static String myToString(int[] arr,boolean flag){ if (arr==null){ return null; } StringBuilder sb = new StringBuilder(); sb.append("["); String str=""; for (int i = 0; i < arr.length; i++) { if(i==arr.length-1){ sb.append(arr[i]); }else{ sb.append(arr[i]+","); } } sb.append("]"); return sb.toString(); }}
💬 数组拷贝
📝 代码示例
🔴 Nick同样写了两个自己版本的拷贝方法(方法2,3,4是java提供的)
import java.lang.reflect.Array;import java.util.Arrays;public class 拷贝数组 { public static void main(String[] args) { int[] arr = {1, 2, 3, 4, 5}; //方法1 自己写 //int[] copy = copyOf(arr); //方法2 Arrays.copyOf(根据长度复制) //int[] ret=Arrays.copyOf(arr,arr.length); //int[] ret=Arrays.copyOf(arr,arr.length*2); //方法3 Arrays.copyOfRange(复制范围) //int[] ret=Arrays.copyOfRange(arr,1,3); //方法4 System.arraycopy (稍微比其他方法快一些) //int[] copy = new int[arr.length]; //System.arraycopy(arr, 0, copy, 0, arr.length); //源码展示// public static native void arraycopy(Object src, int srcPos,// Object dest, int destPos,// int length); //native 所有被native修饰的方法都被C或者C++实现了,速度会比较快 //方法5 (产生一个副本) int[] copy = arr.clone(); System.out.println(Arrays.toString(copy)); } public static int[] copyOf(int[] arr) { int[] arr01 = new int[arr.length]; for (int i = 0; i < arr.length; i++) { arr01[i] = arr[i]; } return arr01; } public static int[] copyOf(int[] arr, int x, int y) { if (arr == null || x = arr.length) { return new int[]{-1}; } else { int length = y - x + 1; int[] arr01 = new int[length]; for (int i = 0; i < length; i++) { arr01[i] = arr[x++]; } return arr01; } }}
🔻注意事项(萌新建议先看上一篇,后面文章会细说)
1.如果有人问道:“以上某某方法是什么拷贝(克隆)?”,最好不要回答,要是一定要说,就说是浅克隆或者画图,深克隆是经过人工干预造成的,不是因为某某拷贝方法就能说是深克隆的。
2.深克隆的实现取决于你的代码怎么写,之后写完类和接口的文章后,Nick会具体介绍深克隆和浅克隆的区别与原理。
3.简单形容一下,深克隆数组(引用类型),就说要将数组中储存的引用类型数据的对象全部备份一波,而不是单纯的拷贝引用数据,浅克隆的话,拷贝的对象引用指向依旧是原来的地址,即多引用指向同一对象。
💬 找数组中的最大元素
🔴 给定一个整型数组, 找到其中的最大元素 (找最小元素同理)
📝 代码示例
public static void main(String[] args) { int[] arr = {1,2,3,4,5,6}; System.out.println(max(arr)); } public static int max(int[] arr) { int max = arr[0]; for (int i = 1; i max) { max = arr[i]; } } return max; }// 执行结果6
🔴 类似于 "打擂台" 这样的过程. 其中 max 变量作为 擂台, 比擂台上的元素大, 就替换上去, 否则就下一个对手
💬 求数组中元素的平均值
🔴 给定一个整型数组, 求平均值
📝 代码示例
public class 数组平均值 { //实现一个方法 avg, 以数组为参数, 求数组中所有元素的平均值(注意方法的返回值类型). public static void main(String[] args) { int[] arr ={1,2,3,4,5,6,7,8,9}; System.out.println(avg(arr)); } public static double avg(int[] arr){ if(arr==null){ System.out.println("null"); }else{ double sum=0.0; for (int i = 0; i < arr.length; i++) { sum+=arr[i]; } return sum/arr.length; } return -1; }}
🔴 类似于 "打擂台" 这样的过程. 其中 max 变量作为 擂台, 比擂台上的元素大, 就替换上去, 否则就下一个对手
🔻 注意事项
结果要用 double 来表示
💬 查找数组中指定元素(顺序查找)
🔴 给定一个数组, 再给定一个元素, 找出该元素在数组中的位置
📝 代码示例
public static void main(String[] args) { int[] arr = {1,2,3,10,5,6}; System.out.println(getIndex01(arr, 3)); }public static int getIndex01(int[] arr,int a){ for (int i = 0; i < arr.length;i++) { if(arr[i]==a){ return i; } } return -1; }//执行结果2
💬 查找数组中指定元素(二分查找)
针对有序数组, 可以使用更高效的二分查找
啥叫有序数组?
- 有序分为 "升序" 和 "降序
- 如 1 2 3 4 , 依次递增即为升序
- 如 4 3 2 1 , 依次递减即为降序
🔴 以升序数组为例, 二分查找的思路是先取中间位置的元素, 看要找的值比中间元素大还是小. 如果小, 就去左边找; 否 则就去右边找
📝 代码示例
import java.util.Arrays;import java.util.Scanner;//二分查找public class 数组索引二分 { public static void main(String[] args) { int[] arr = {1,2,5,6,7,8,6}; Scanner src=new Scanner(System.in); int a=src.nextInt(); //System.out.println(getIndex02(arr,a)); //这个是java自带查找索引的方法 //System.out.println(Arrays.binarySearch(arr,a)); } public static int getIndex02(int[] arr,int a){ int left=0; int right=arr.length-1; while(left arr[mid]){ left=mid+1; }else if(a < arr[mid]){ right=mid-1; }else if(a==arr[mid]){ return mid; } } return -1; }}
💬 感受二分查找的效率
class Test { static int count = 0; // 创建一个成员变量, 记录二分查找循环次数 public static void main(String[] args) { int[] arr = makeBigArray(); int ret = binarySearch(arr, 9999); System.out.println("ret = " + ret + " count = " + count); } public static int[] makeBigArray() { int[] arr = new int[10000]; for (int i = 0; i < 10000; i++) { arr[i] = i; } return arr; } public static int binarySearch(int[] arr, int toFind) { int left = 0; int right = arr.length - 1; while (left <= right) { count++; // 使用一个变量记录循环执行次数 int mid = (left + right) / 2; if (toFind arr[mid]) { // 去右侧区间找 left = mid + 1; } else { // 相等, 说明找到了 return mid; } } // 循环结束, 说明没找到 return -1; }} // 执行结果 ret = 9999 count = 14
🔴 可以看到, 针对一个长度为 10000 个元素的数组查找, 二分查找只需要循环 14 次就能完成查找. 随着数组元素个数 越多, 二分的优势就越大.