Java:深入了解数组Arrays.binarySearch方法的优缺点
目录
最近重新整理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,这是因为>>>可以提高编程的运行速度