Java常用类库之Arrays类
Arrays是Java类库中对于数组的支持类,里面不仅有例如Arrays.sort()对数组排序的方法,还提供很多其他方法。
序号 | 方法名称 | 描述 |
---|---|---|
1 | public static int binarySearch(数据类型[] a,数据类型[] key) | 二分查找法,也是现在对于所谓的查找性能的最佳优化,返回的数据的索引位置 |
2 | public static int compare(数据类型[] a,数据类型[] b) | 两个数组的大小比较 |
3 | public static double[] copyOf(double[] original,int newLength) | 数组拷贝,从原始数组拷贝内容到新的数组 |
4 | public static boolean equals(数据类型 a,数据类型[] a2) | 两个数组的相等比较(顺序要相同) |
5 | public static void fill(数据类型 a,数据类型 val) | 数组填充 |
6 | public static int hashCode(数据类型[] a) | 根据数组内容生成一个新的Hash码 |
7 | public static void sort(数据类型[] a) | 数组排序 |
8 | public static String toString(数据类型[] a) | 将数组转换为字符串 |
Arrays类所提供的所有方法全部都属于static方法,并且其构造方法也已经被private封装了,同时由于在实际的开发中数组的类型比较多,所以很多的方法都会进行大量的重载处理。
范例: 观察Arrays基本使用
public class ArraysDemo {
public static void main(String[] args) {
int [] data = new int[]{1,5,7,2,90,23,56,78};
System.out.println("原始数组内容:"+ Arrays.toString(data));
Arrays.sort(data);
System.out.println("排序后的数组内容:"+ Arrays.toString(data));
}
}
执行结果:
原始数组内容:[1, 5, 7, 2, 90, 23, 56, 78]
排序后的数组内容:[1, 2, 5, 7, 23, 56, 78, 90]
如果要想使用Arrays类中的equals()比较两个数组的内容是否相同,那么一定要保证两个数组的内容顺序是一致的。
范例: 比较两个数组的内容是否相同
public class ArraysDemo {
public static void main(String[] args) {
int [] dataA = new int[]{1,7,5};
int [] dataB = new int[]{5,7,1};
System.out.println("【相等判断 - 未排序】" + Arrays.equals(dataA,dataB));
Arrays.sort(dataA);
Arrays.sort(dataB);
System.out.println("【相等判断 - 未排序】" + Arrays.equals(dataA,dataB));
System.out.println("【大小关系判断】" + Arrays.compare(new int[5.8.9],dataA));//注意:compare()方法JDK9(包含)以后才支持
}
}
执行结果:
【相等判断 - 未排序】false
【相等判断 - 未排序】true
【大小关系判断】1
在使用Arrays类中提供的compare()方法的时候,一般会有三种返回结果:大于(1),等于(0),小于(-1)。
在整个Arrays类中提供一个最为重要的数组的内容查找方法:二分查找法(只要牵扯到面试的问题,这类问题一定都会问到),如果要想理解二分查找法的概念,那么首先就必须来分析一下关于数组内容的查找操作。
范例: 实现数组内容的查找
public class ArraysDemo {
public static void main(String[] args) {
int [] data = new int[]{9,8,5,19,29,56,78,3};
int key = 9;//要查找的关键数据
System.out.println(search(data,key));
}
/**
* 本方法的主要作用是查找在指定的数组之中是否存在有指定的数据内容
* 如果存在则返回相应的索引,如果不存在返回-1
* @param data 被查找的数组
* @param key 要查找的数据
* @return 数组索引,未找到返回-1
*/
public static int search(int [] data,int key){
for (int i = 0; i < data.length; i++) {
if(data[i] == key){ //满足数据查询要求
return i; //返回当前索引
}
}
return -1;
}
}
执行结果:
0
对于以上数据的查找实际上它的原理非常简单:就是对数组中的每一个数据进行逐个排查,现在假设有100个长度的数组,那么最多排查100次,如果有10W个数组的长度,那么最多排查10W次,按照程序的设计概念来讲,此时search()方法时间复杂度为“O(n)”(n为数组长度),并且随着内容的增加,时间复杂度还会攀升,如果要想进行性能的优化,就必须对整个的结构进行重新设计,在整个计算机的世界里,如果按照查找来讲,最快的速度就是“O(log2N)”,这个时候就可以采用二分查找法,而这种二分查找法实现前提是需要数组做出排序。
下面观察一下二分查找法的具体实现思路:
每次只需查找对应目标数据的一半,从而提升性能。
首先来看源码:
// Like public version, but without range checks.
private static int binarySearch0(int[] a, int fromIndex, int toIndex,
int key) {
int low = fromIndex;
int high = toIndex - 1;
while (low <= high) {
int mid = (low + high) >>> 1;
int midVal = a[mid];
if (midVal < key)
low = mid + 1;
else if (midVal > key)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found.
}
范例: 实现二分查找法(参考Arrays类的二分查找实现)
public class ArraysDemo {
public static void main(String[] args) {
int [] data = new int[]{3,10,5,9,1,7};
System.out.println("【原始数组】" + Arrays.toString(data));
int key = 9;//要查找的关键数据
Arrays.sort(data);
System.out.println("【排序后数组】" + Arrays.toString(data));
System.out.println("【数据查询】"+search(data,key));
}
/**
* 本方法的主要作用是查找在指定的数组之中是否存在有指定的数据内容
* 如果存在则返回相应的索引,如果不存在返回-1
* @param data 被查找的数组
* @param key 要查找的数据
* @return 数组索引,未找到返回-1
*/
public static int search(int [] data,int key){
int low = 0; // 开始索引
int high = data.length - 1;//结束索引
//现代的语言设计过程之中,强调通过循环结构来代替递归结构,这样可以提升处理性能
while (low <= high) {
int mid = (low + high) >>> 1; // 进行中间索引的确定,折半
int midVal = data[mid]; // 获取中间数据
if (midVal < key) //判断中间值是否小于要查找的内容
low = mid + 1; //修改low的值,为“中间索引+1”
else if (midVal > key) //判断中间值是否大于要查找的内容
high = mid - 1; //不再判断后面,然后修改high,从而缩小查找范围
else //数据匹配成功
return mid; // 返回当前索引
}
return -(low + 1); // 负数,未查询到
}
}
执行结果:
【原始数组】[3, 10, 5, 9, 1, 7]
【排序后数组】[1, 3, 5, 7, 9, 10]
【数据查询】4
假设当前的数组内容组成为:new int[]{3,10,5,9,1,7},于是在整个二分查找的操作之中具体的变量的数据如下:
- 初始化:low = 0 (数组的首个索引)、high = 5 (数组的尾索引);
- while循环,判断依据:low < high;
- 第 1 次循环:mid (“(low + high) >>> 1” —— 5【101]】>>> 1 ——2【10】)、low = 3
- 第 2 次循环:min(“3 + 5 = 8”——8【1000】>>> 1 ——4【100】)
现代的开发由于在系统类库里面所提供的方法都已经非常到位了,所以在整个的执行过程中,实际上就可以直接利用Arrays类提供的二分查找法进行简单的调用即可,但是依然需要注意,数组排序是实现二分查找的操作前提。
范例: 直接使用Arrays类中的二分查找
public class ArraysDemo {
public static void main(String[] args) {
int [] data = new int[]{3,10,5,9,1,7};
System.out.println("【原始数组】" + Arrays.toString(data));
int key = 9;//要查找的关键数据
Arrays.sort(data);
System.out.println("【排序后数组】" + Arrays.toString(data));
System.out.println("【数据查询】"+Arrays.binarySearch(data,key));
}
}
执行结果同上。
结语: 以上例子就想说明:虽然Arrays类给我们提供好了这个方法供我们调用,但我们依然需要分析其底层实现原理,其实这种就属于数据结构的实现,而当我们在实际找工作过程中,开发未必使用到它,但是在面试的时候这些都叫基础的实现原理,这些基础的实现原理大家必须清楚,因为有一些要求比较严格的公司会要求我们现场写二分查找,我们总不能直接写一个"Arrays.binarySearch()"方法名吧?所以如果在日后找工作的时候,考到你二分查找功能的时候,就将该方法源代码写出来即可。