二分查找也称为折半查找,是对有序元素查找的一种算法,在查找的过程中,不断的将搜索长度减半,因此效率不错。Java的JDK提供了二分法查找的算法,使用的方法是Arrays.binarySearch()。binarySearch()方法提供了多种数据类型的二分查找,比如实现了int、float、double、char、byte和Object类型,还提供了对泛型的支持。在JavaAPI手册中提供了接口说明,比如如下方法:

 static int binarySearch(long[] a, int fromIndex, int toIndex, long key)
static int binarySearch(long[] a, long key)
static int binarySearch(Object[] a, int fromIndex, int toIndex, Object key)
static int binarySearch(Object[] a, Object key)
static int binarySearch(short[] a, int fromIndex, int toIndex, short key)
static int binarySearch(short[] a, short key)
static <T> int binarySearch(T[] a, int fromIndex, int toIndex, T key, Comparator<? super T> c)
static <T> int binarySearch(T[] a, T key, Comparator<? super T> c)

  以上是Arrays类中提供的部分关于binanrySearch()方法的定义,对于不同类型来说,基本提供了两种方法,第一种方法需要在调用时提供数组、开始下标、结束下标和查找的值,比如:

static int binarySearch(long[] a, int fromIndex, int toIndex, long key)

  另外一种查找的方法是提供数组和查找的值即可,比如:

static int binarySearch(long[] a, long key)

  对于这两种搜索方法,在Java中提供了统一的调用方法,可以查看其代码,在Java的安装目录下找到src.zip文件,该文件是Java的部分源码。将src.zip文件解压缩,在java/util/Arrays.java中可以找到以上两个方法的实现,代码如下:

 public static int binarySearch(long[] a, long key) {
return binarySearch0(a, 0, a.length, key);
} public static int binarySearch(long[] a, int fromIndex, int toIndex,
long key) {
rangeCheck(a.length, fromIndex, toIndex);
return binarySearch0(a, fromIndex, toIndex, key);
}

  从代码中可以看到,两个方法最后都调用了binarySearch0()方法,但是在第二个binarySearch()方法中调用了rangeCheck()方法,该方法用于检查数组长度、开始下标和结束下标的正确性,rangeCheck()方法的实现如下:

 /**
* Checks that {@code fromIndex} and {@code toIndex} are in
* the range and throws an exception if they aren't.
*/
private static void rangeCheck(int arrayLength, int fromIndex, int toIndex) {
if (fromIndex > toIndex) {
throw new IllegalArgumentException(
"fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
}
if (fromIndex < 0) {
throw new ArrayIndexOutOfBoundsException(fromIndex);
}
if (toIndex > arrayLength) {
throw new ArrayIndexOutOfBoundsException(toIndex);
}
}

  如果调用第一个binarySearch()方法,数组长度、开始下标和结束下标是方法中自行获取的,因此不需要进行rangeCheck(),而调用第二个binarySearch()方法时,数组长度、开始下标和结束下标是调用时外部提供的,因此为了保证正确性进行了rangeCheck()。

  二分法真正的实现是binarySearch0()方法,根据不同的数据类型,binarySearch0()方法也提供了多种重载,这里只看long类型的实现,代码如下:

 private static int binarySearch0(long[] a, int fromIndex, int toIndex,
long key) {
int low = fromIndex;
int high = toIndex - 1; while (low <= high) {
int mid = (low + high) >>> 1;
long 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.
}

  二分查找的思路是从有序(从小到大)数组的中间位置开始查找,如果中间位置的数小于查找的目标值,则查找数组中间值右侧的部分,如果中间位置的数大于查找的目标值,则查找数组中间值左侧的部分,如果相等,则返回当前的下标,如果没有找到则返回一个负数。

  除了上面的实现外,还有一种针对泛型的binarySeach()的方法,如下:

 static <T> int binarySearch(T[] a, int fromIndex, int toIndex, T key, Comparator<? super T> c)
static <T> int binarySearch(T[] a, T key, Comparator<? super T> c)

  在上面两个方法的定义中,最后一个参数是一个比较器,比较器的作用是比较两个元素的大小用的,查看以上两个方法的实现,代码如下:

 public static <T> int binarySearch(T[] a, T key, Comparator<? super T> c) {
return binarySearch0(a, 0, a.length, key, c);
} public static <T> int binarySearch(T[] a, int fromIndex, int toIndex,
T key, Comparator<? super T> c) {
rangeCheck(a.length, fromIndex, toIndex);
return binarySearch0(a, fromIndex, toIndex, key, c);
}

  以上两个方法同样调用了binarySearch0()方法,该binarySearch0()方法的实现代码如下:

 private static <T> int binarySearch0(T[] a, int fromIndex, int toIndex,
T key, Comparator<? super T> c) {
if (c == null) {
return binarySearch0(a, fromIndex, toIndex, key);
}
int low = fromIndex;
int high = toIndex - 1; while (low <= high) {
int mid = (low + high) >>> 1;
T midVal = a[mid];
int cmp = c.compare(midVal, 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.
}

  观察代码的第12行,c是比较器,该比较器中提供了一个compare()方法用来比较两个元素的大小,如果midVal比key小,compare返回负数,如果midVal比key大,compare返回整数,如果midVal和key相等,compare则返回0。

  以上就是在学习Arrays工具类的使用时,顺便阅读了它的实现,而刚好又能看懂,所以记录在此!


我的微信公众号:“码农UP2U”

Arrays的二分查找的更多相关文章

  1. JAVA基础系列:Arrays.binarySearch二分查找

    首先,binarySearch方法为二分法查找,所以数组必须是有序的或者是用sort()方法排序之后的 1)  binarySearch(Object[] a, Object key) a: 要搜索的 ...

  2. JAVA源码走读(二)二分查找与Arrays类

    给数组赋值:通过fill方法. 对数组排序:通过sort方法,按升序.比较数组:通过equals方法比较数组中元素值是否相等.查找数组元素:通过binarySearch方法能对排序好的数组进行二分查找 ...

  3. 《java入门第一季》之Arrays类前传(排序案例以二分查找注意的问题)

    根据排序算法,可以解决一些小案例.举例如下: /* * 把字符串中的字符进行排序. * 举例:"dacgebf" * 结果:"abcdefg" * * 分析: ...

  4. 零基础学习java------day12------数组高级(选择排序,冒泡排序,二分查找),API(Arrays工具类,包装类,BigInteger等数据类型,Math包)

    0.数组高级 (1)选择排序 它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的起始位置 ...

  5. 二分查找算法java实现

    今天看了一下JDK里面的二分法是实现,觉得有点小问题.二分法的实现有多种今天就给大家分享两种.一种是递归方式的,一种是非递归方式的.先来看看一些基础的东西. 1.算法概念. 二分查找算法也称为折半搜索 ...

  6. Java-数据结构与算法-二分查找法

    1.二分查找法思路:不断缩小范围,直到low <= high 2.代码: package Test; import java.util.Arrays; public class BinarySe ...

  7. page61-将二分查找重写为一段面向对象的程序

    1 将二分查找重写为一段面向对象的程序 (用于在整数集合中进行查找的一种抽象数据类型) public class StaticSETofInts [API] StaticSETofInts(int[] ...

  8. Java学习之二分查找算法

    好久没写算法了.只记得递归方法..结果测试下爆栈了. 思路就是取范围的中间点,判断是不是要找的值,是就输出,不是就与范围的两个临界值比较大小,不断更新临界值直到找到为止,给定的集合一定是有序的. 自己 ...

  9. 二分查找(binary search)

    二分查找又叫折半查找,要查找的前提是检索结果位于已排序的列表中. 概念 在一个已排序的数组seq中,使用二分查找v,假如这个数组的范围是[low...high],我们要的v就在这个范围里.查找的方法是 ...

随机推荐

  1. Web开发笔记

    jquery ui draggable clone之后不会克隆draggable功能,要重新设置

  2. 二、配置QtDesigner、PyUIC及PyRcc

    配置QtDesigner.PyUIC及PyRcc 安装完PyQt 5 及PyQt5-tools 后,则需要在Pycharm中配置QtDesigner.PyUIC及PyRcc. 配置QtDesigner ...

  3. Java-Maven(一):Maven的简介与安装

    Maven的简介 Maven是什么? Maven是一个项目管理和整合的工具.Maven为开发者提供了一套完整的构建生命周期框架.开发者可以通过Maven更快的自动完成工程的基础构建陪孩子,因为Mave ...

  4. POJ-3723 Conscription---最大权森林---最小生成树

    题目链接: https://vjudge.net/problem/POJ-3723 题目大意: 需要征募女兵N人, 男兵M人. 每征募一个人需要花费10000美元. 带式如果已经征募的人中有一些关系亲 ...

  5. Thymeleaf3语法详解和实战

    Thymeleaf3语法详解 Thymeleaf是Spring boot推荐使用的模版引擎,除此之外常见的还有Freemarker和Jsp.Jsp应该是我们最早接触的模版引擎.而Freemarker工 ...

  6. jacascript 偏移量offset、客户区client

    前言:这是笔者学习之后自己的理解与整理.如果有错误或者疑问的地方,请大家指正,我会持续更新! 偏移量 偏移量(offset dimension)是 javascript 中的一个重要的概念.涉及到偏移 ...

  7. poj1182-食物链-带权并查集-种类并查集

    (这应该是我写的第一个和带权并查集相关的题,还不是很了解,所以这篇博客我以后还会做修改,力求更号理解! 题意和思路: 中文题意,我简单提一下: A->B,B->C,C->A.A吃B, ...

  8. List<E> 接口简明

    java.util.List<E>接口. ListIterator.equals 方法 List 是 Collection 接口的子接口,具备了 Collection 的所有方法. Lis ...

  9. Multipath在OpenStack中的faulty device的成因及解决(part 1)

    | 版权:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接.如有问题,可以邮件:wangxu198709@gmail.com 简介: Multip ...

  10. 学习HTML的第二次课

    1.图片 <img / > 图片的格式: 1.1BMP 占用空间大,颜色丰富. 1.2JPEG 有损压缩,占用空间较小. 1.3GIF 多帧动图,支持透明色. 1.4PNG 无损压缩,位图 ...