Arrays.binarySearch()方法

    Arrays.binarySearch()方法用于对有序的数组寻找某一对象的位置,其对象数组必须实现Comparable接口,不然就会报错java.lang.ClassCastException首先写两个小例子验证方法:

首先是基本类型int数组:

public static void testIntSearch() {
	int[] array = new int[10];
	Random random = new Random(47);
	for (int i = 0; i < array.length; i++) {
		array[i] = random.nextInt(30);
	}
	//记录array[0]的值
	int flag = array[0];
	System.out.println("排序之前的array:" + Arrays.toString(array));
	Arrays.sort(array);
	System.out.println("排序之后的array:" + Arrays.toString(array));
	System.out.println("array[0]=" + flag + ",排序之后的位置:" + Arrays.binarySearch(array, flag));
	System.out.println("2在数组中的位置:" + Arrays.binarySearch(array, 2));
	System.out.println("-10在数组中的位置:" + Arrays.binarySearch(array, -10));
	System.out.println("100在数组中的位置:" + Arrays.binarySearch(array,100));
}

输出:

排序之前的array:[8, 5, 13, 11, 1, 29, 28, 20, 12, 7]
排序之后的array:[1, 5, 7, 8, 11, 12, 13, 20, 28, 29]
array[0]=8,排序之后的位置:3
2在数组中的位置:-2
-10在数组中的位置:-1

100在数组中的位置:-11


        数组虽然是Random生成的,但是Random构造参数seed指定之后,random.nextInt(30)每次生成的数字此时就不是随机的数字,也就是说array数组生成的时候每次都是相同的。用flag记录array[0]的值,然后查看排序之后flag的位置。由输出知道flag=8,排序之后其在数组中的位置为3,也就是排序之后flag=array[3]。而若数组中不存在的数字进行查询,如2,其返回为-2,这个值是按照排序规则其插入点决定的,假设其插入点位置为index,则返回值为-(index+1)。如果插入点在数组最开始的地方则返回统一为-1;而插入点在数组末尾,则返回与数组长度有关,假设数组长度为length,则返回为-(length+1)。

        上面的验证用的是int型的数组,下面用一般的对象型数组

public static class E23 implements Comparable {
		private int value;

		public E23(int value) {
			this.value = value;
		}

		@Override
		public String toString() {
			return value + "";
		}

		@Override
		public int compareTo(E23 o) {
			if (this.value > o.value) {
				return 1;
			} else if (this.value < o.value) {
				return -1;
			} else {
				return 0;
			}
		}
		
		public static void main(String[] args) {
			E23[] a = new E23[10];
			Random random = new Random();
			for (int i = 0; i < a.length; i++) {
				a[i] = new E23(random.nextInt(10));
			}
			E23 e23 = a[0];
			System.out.println(Arrays.toString(a));
			Arrays.sort(a);
			System.out.println(Arrays.toString(a));
			System.out.println(e23.value + "在数组中位置:" + Arrays.binarySearch(a, e23));
		}
	}

        在刚开始的时候,由于没有继承Comparable,所以运行时报了异常,根据异常猜测是需要继承Comparable接口,此处并未深究,原因放到后面源码的解释。E23是一个简单的类,有一个private的int域参数,继承Comparable接口实现comparaTo方法,此处用的是int域比较大小,此处要注意必须返回三种情况的值,大于小于和等于,等于返回0,其他两种情况则根据想制定的排序顺序。由结果可以知道对象类型的排序后的数组也是可查找的,其结果与基础类型一样。

        下面就来看一下Arrays.binarySearch()方法的源码:此处用到的是binarySearch(int[] a,int key)与binarySearch(T[] a,T key),我们就看一下一般类型binarySearch(T[] a,T key)方法:

public static int binarySearch(Object[] a, Object key) {
        return binarySearch0(a, 0, a.length, key);
    }

可以看到其底层其实是binarySearch0(a, 0, a.length, key)方法,继续查看该方法:

private static int binarySearch0(Object[] a, int fromIndex, int toIndex,
                                     Object key) {
        int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            @SuppressWarnings("rawtypes")
            Comparable midVal = (Comparable)a[mid];
            @SuppressWarnings("unchecked")
            int cmp = midVal.compareTo(key);

            if (cmp < 0)
                low = mid + 1;
            else if (cmp > 0)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found.
    }
该方法应该就是查找元素的最基本的算法实现了。由于没有指定fromIndex与toIndex,所以默认就是整个数组查找,在while循环中使用了二分法的算法思想查找元素在数组中的位置,while中第一行的意思是找到二分之后区域的中间位置,下面一行代码就解释了为什么要继承Comparable了,如果不继承Comparable此处必然会报出类型转换错误的异常,再下面调用compareTo方法进行比较,在此处就知道了为什么该方法只能用于排序之后的数组了,此处的二分法就是建立在数组是有序的前提之下,如果是没有顺序的,那就有可能出现各种情况。

你可能感兴趣的:(Arrays.binarySearch()方法)