目录
- 背景
- 方法介绍
- 实例
- 结果
- 缺点
- 实例
- 结果
- 分析原因
- 源码说明
- 补充说明
背景
最近重新整理Java基础知识,在练习数组的过程中关于Arrays.binarySearch(type[] a,type key)方法的一系列问题以及解决方法
方法介绍
Arrays.binarySearch(type[] a,type key),第一个输入的值为相应数据类型的数组,第二个为想要查找的数值,如果查询到这个数值就会返回该数值的下标,如果没有找到,则返回插入值的负数。
PS:在使用Arrays.binarySearch(type[] a,type key)方法前,需要对数组进行排序
实例
int[] num=new int[]{5,8,3,10,1};
//对数组进行排序
Arrays.sort(num);
//排序后的数组为[1,3,5,8,10]
//查询数组num数值为8的下标,有结果,返回下标
int num1=Arrays.binarySearch(num,8);
//查询数组num数值为6的下标,无结果,返回-1或“-”(插入点)。插入点是索引键将要插入数组的那一点,即第一个大于该键的元素的索引。
int num2=Arrays.binarySearch(num,6);
int num3=Arrays.binarySearch(num,-6);
//查询数值num中下标为2到3中数值为8的下标
int num4=Arrays.binarySearch(num,2,3,8);
//查询数值num中下标为1到3中数值为3的下标
int num5=Arrays.binarySearch(num,1,3,3);
System.out.println("查询数组num数值为8的下标,有结果"+num1);
System.out.println("查询数组num数值为6的下标,无结果"+num2);
System.out.println("查询数组num数值为-6的下标,无结果"+num3);
System.out.println("查询数值num中下标为2到3中,数值为8的下标"+num4);
System.out.println("查询数值num中下标为2到3中,数值为3的下标"+num5);
结果
方法缺点:
到这一步这个方法一切都是如此简单,我就不会写这个博客了,但是这个方法有1个无法解决的缺点,让我们先看一下Java自己是如何介绍这个方法的。
对于英语不好的朋友我把第一段已经翻译后,显示在下面
使用二进制搜索算法在指定的整数数组中搜索指定的值。在进行此调用之前,必须对数组进行排序(就像使用{@link#sort(int[])}方法一样)。如果不排序,则结果未定义。
如果数组包含多个具有指定值的元素,则无法保证将找到哪一个元素。
我加粗的那一行字,也就是说如果数值中有多个重复的值,它可能就无法正确定位到该位置。
实例
int[] num=new int[20];
for (int i=0;i<num.length;i++){
Random random=new Random();
num[i]=random.nextInt(3)+1;
}
Arrays.sort(num);
int num1=Arrays.binarySearch(num,1);
int num2=Arrays.binarySearch(num,2);
int num3=Arrays.binarySearch(num,3);
System.out.println("1的下标"+num1);
System.out.println("2的下标"+num2);
System.out.println("3的下标"+num3);
结果
返回结果
实际结果
总结:所以当有多个相同的数值在数组中,Arrays.binarySearch方法无法正确找到该数值的最后一个数值的索引,或者第一个数值的索引。
原因分析
源码查看:查看Arrays.binarySearch()方法,这里以int类型作为解说
public static int binarySearch(int[] a, int key) {
return binarySearch0(a, 0, a.length, key);
}
public static int binarySearch(int[] a, int fromIndex, int toIndex,int key) {
rangeCheck(a.length, fromIndex, toIndex);
return binarySearch0(a, fromIndex, toIndex, key);
}
// 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.binarySearch()方法实际上就是调用binarySearch0()方法,binarySearch0()方法其实是一个二分查找法,这就是为什么我们使用Arrays.binarySearch()前需要进行排序,以及多个数值相同的数,无法精确定位下标的原因。
补充说明:
当没有定义int fromIndex, int toIndex时,fromIndex=0, toIndex=数组长度
为什么使用>>>(无符号位右移),而不是用>>(右移)这是避免数据过大,导致溢出
为什么使用>>>位运算符,而不是直接除以2,这是因为>>>可以提高编程的运行速度