binarySearch() 只适用于已排序数组,因其底层二分查找依赖“左小右大”的有序结构来每次排除一半搜索空间;未排序时可能跳过目标、返回负数或错误正索引,且不校验排序状态。

binarySearch() 为什么只认已排序数组
Arrays.binarySearch() 的底层是二分查找,每次比较都依赖“左小右大”的有序结构来砍掉一半搜索空间。如果数组没排过序,它可能跳过目标、返回负数,甚至返回错误的正索引——这不是 bug,是设计前提被破坏了。别指望它帮你“容错”,它连是否已排序都不检查,直接开搜。
常见错误现象:binarySearch() 返回负数(比如 -3),你以为没找到,其实可能是你传进去的数组根本没排序;或者返回一个看似合理的正数索引,但对应元素根本不是你要找的——这通常发生在你误以为数组已排序,实际只是“看起来差不多”(比如含重复值且顺序混乱)。
- 使用前务必确认:调用
Arrays.sort()或确保数据来源天然有序(如数据库按主键升序导出) - 对
int[]、String[]等基本类型/引用类型数组,排序和查找必须用同一套比较逻辑(比如都用自然序,或都传同一个Comparator) - 若数组由外部输入,建议加一层校验(例如遍历检查
arr[i] ),尤其在测试环境暴露问题比线上报 <code>ArrayIndexOutOfBoundsException强得多
查不到时返回的负数到底是什么
当 binarySearch() 没找到目标,它不简单返回 -1,而是返回 -(insertionPoint) - 1,其中 insertionPoint 是目标应插入的位置(即保持有序的最小索引)。这个设计其实很有用,但容易被忽略。
举例:数组 [1, 3, 5, 7] 中查 4,返回 -3(因为 4 应插在索引 2,所以 -(2) - 1 = -3)。你可以用 ~returnVal(按位取反)快速还原插入点:int pos = ~(-3); // 得 2。
- 不要用
result 就直接判定“不存在”然后扔异常——有时你需要知道它该插哪(比如维护有序列表) - 负数返回值与数组长度无关,只取决于比较过程;哪怕数组为空,查任意值也返回
-1(因为insertionPoint = 0,故-(0)-1 = -1) - 对对象数组,若自定义
Comparator逻辑有误(比如不满足传递性),可能导致插入点计算错乱,此时负数也不再可靠
原始类型数组和泛型数组的调用差异
Arrays.binarySearch() 对原始类型(如 int[])和引用类型(如 Integer[])提供不同重载,不能混用。传 int[] 却用 binarySearch(Object[], Object) 会编译失败;而传 Integer[] 却用 binarySearch(int[], int) 也会报错——Java 不自动拆箱整个数组。
性能影响明显:对百万级 int[],用 binarySearch(int[], int) 比用 Integer[] 快 3–5 倍,因为后者涉及装箱/拆箱和对象引用跳转。
- 原始类型数组必须用对应重载:查
double[]用binarySearch(double[], double),不能用泛型版 -
String[]属于引用类型,用binarySearch(String[], String);若用Comparator,必须传binarySearch(String[], String, Comparator) - 泛型版(如
T[])要求T实现Comparable,否则编译不过;若想绕过,只能显式传Comparator
重复元素时 binarySearch() 返回哪个索引
Arrays.binarySearch() 不保证返回第一个或最后一个匹配项,只保证返回“某个匹配索引”。在 [2, 4, 4, 4, 6] 中查 4,可能返回 1、2 或 3,取决于内部比较路径——这是二分查找的固有不确定性,不是实现缺陷。
如果你需要最左或最右位置(比如统计频次、找边界),不能依赖单次 binarySearch()。得自己写边界查找,或用两次调用逼近(例如先查到一个位置,再向左线性探查到第一个 4)。
- 别用
binarySearch()结果直接做“删除首个匹配项”之类操作——删错位置的风险很高 - 若业务强依赖边界,建议封装
findFirst()/findLast()方法,内部用 while 循环微调,比反复调用binarySearch()更稳 - Java 9+ 的
Arrays.mismatch()或Stream不解决这个问题——它们不提供有序数组的边界定位能力
真正极速的前提,是接受它的契约:只处理确定有序、无歧义比较、且你不需要唯一位置语义的场景。一旦涉及重复、动态插入或弱排序,就得自己补逻辑——binarySearch() 聪明,但不替你做判断。

















