之前一篇文章中已经解过一道 leetcode 二分查找的题目了,这篇文章再来分析一下 java 类库中提供的二分查找源码。
对应的类为 java.util.Arrays,方法名为 binarySearch。
1
可以看到:
- 贴心的提供了所有类型数组的二分查找方法
- 每种类型都提供了两种二分查找方法:
- 两个参数(最后一个三个参数):从整个数组中查找
- 四个参数(倒数第二个五个参数):从数组指定的范围中查找,中间的两个参数指定范围,该范围为前闭后开
每种类型数组的两种二分查找方法底层调用的都是同一个叫做 binarySearch0 的私有方法,因此 binarySearch0 也对应提供了不同类型的方法。binarySearch0 支持从数组指定的范围中查找,同样,中间的两个参数用来指定范围,该范围为前闭后开。
int[]
这部分主要以 int 类型数组的二分查找源码为例,来看看是怎么写的。
- 先来看两个参数的 binarySearch 方法。可以看到底层调用 binarySearch0 方法,中间两个参数是 0 和 a.length,即从数组 a 的 [0, a.length) 范围中查找目标值 key。
- 再来看四个参数的 binarySearch 方法。可以看到底层同样调用 binarySearch0 方法,中间两个参数是 fromIndex 和 toIndex,即从数组 a 的 [fromIndex, toIndex) 范围中查找目标值 key。
但是在调用 binarySearch0 方法之前,会调用 rangeCheck 方法来检查 fromIndex 和 toIndex 的合法性,不合法则抛出异常。
关于这两个参数的合法性,下面截图中方法注释的 @throws 部分写的非常明白(良心博主,翻译都安排的明明白白),不再赘述。
检查 fromIndex 和 toIndex 合法性的代码也非常简单。
- 最后来看 binarySearch0 方法,会发现,代码几乎和之前 leetcode 二分查找那篇文章中我们写的一样,唯一的区别是:如果没找到目标值 key 时的返回值。
关于这点,上面截图中方法注释的 @return 部分也写的非常明白,不再赘述。
关于没找到目标值 key 时为什么返回的是 -(插入点) - 1 的证明方法,在这里也共享出一个链接以供大家阅读:
https://blog.csdn.net/paralysed/article/details/106583034
3
其它类型数组的二分查找源码和 int 类型的大同小异,这部分来具体看看。
byte[]、char[]、long[]、short[] 和 int[] 一样,大小比较用的都是大于小于的方式
Object[] 大小比较用的是 Comparable.compareTo 方法
- T[] 的大小比较,最后一个参数可以传自定义比较器,如果没传,则默认走的是 Object[] 的二分查找方法
- float[] 和 double[] 的大小比较方法和前面类型的都有一点点不一样。不过还好,我们已经了解了 IEEE 754 标准,并且在上一篇一起分析过 Float.java 和 Double.java 的源码,所以,直接上代码(该部分代码对应其 compare 方法源码)