目录

  • 背景
  • 方法介绍
  • 实例
  • 结果
  • 缺点
  • 实例
  • 结果
  • 分析原因
  • 源码说明
  • 补充说明

背景

最近重新整理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);

结果

array java语言 java arrays.binarysearch_System

 

方法缺点:

到这一步这个方法一切都是如此简单,我就不会写这个博客了,但是这个方法有1个无法解决的缺点,让我们先看一下Java自己是如何介绍这个方法的。

array java语言 java arrays.binarysearch_数组_02

 对于英语不好的朋友我把第一段已经翻译后,显示在下面

使用二进制搜索算法在指定的整数数组中搜索指定的值。在进行此调用之前,必须对数组进行排序(就像使用{@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);

结果

返回结果

array java语言 java arrays.binarysearch_System_03

 

 实际结果

array java语言 java arrays.binarysearch_System_04

 

 总结:所以当有多个相同的数值在数组中,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,这是因为>>>可以提高编程的运行速度