arrays.binarysearch要求数组升序,否则结果无定义;返回值≥0表示存在并给出索引,

Arrays.binarySearch 不是“一调就灵”的黑盒方法,它背后是一套有前提、有边界、有细节的检索逻辑。用对了,O(log n) 高效稳定;用错了,结果看似合理实则不可靠,且不报错、不警告。
必须升序,否则结果无定义
二分查找依赖“中点值能划分搜索区间”这一前提。只有升序数组才能保证:若 target arr[mid],目标一定在右半段。一旦数组乱序,比较结果就会误导搜索路径,返回值既不是真实索引,也不符合插入点规则——它只是算法在错误输入下运行出的任意整数。
- 官方文档明确要求“the array must be sorted in ascending order”,这是契约,不是建议
- 降序数组不能直接使用;如需支持,排序和查找都必须传入同一 Comparator(如 Collections.reverseOrder())
- 常见误操作:从数据库/文件读取后未排序就调用;排序后又修改了某个元素;误以为“基本有序”就能用
返回值不是布尔,而是位置编码
返回值携带双重语义:正数表示存在且给出索引;负数表示不存在,但隐含插入位置。这个设计让 binarySearch 不仅能查,还能辅助维护有序结构。
- ≥ 0:目标存在,数值即其在数组中的索引(从 0 开始)
- < 0:目标不存在,插入点 = -(返回值 + 1),即该值应插入的位置索引
- 例如返回 -4 → 插入点为 3;返回 -1 → 插入点为 0(应插在开头);返回 -7(数组长为 6)→ 插入点为 6(应插在末尾)
- 切忌用 result == -1 判断失败——那仅代表“应插在开头”,不是通用失败标志
小数组走线性扫描,大数组才启用二分
为兼顾现代 CPU 缓存与分支预测特性,JDK 实现做了性能优化:长度小于阈值(JDK 8 中为 21)时,直接遍历;超过阈值才进入标准二分流程。
- 小数组线性扫描更快,避免反复计算 mid、跳转带来的开销
- 大数组采用 low + (high - low) / 2 计算中点,防止整数溢出
- 循环条件为 low
- 未找到时统一返回 -(low + 1),逻辑清晰且便于还原插入点
类型与比较逻辑必须严格匹配
binarySearch 有多个重载,但每种版本对输入都有明确约束,混用会导致编译通过但运行异常或结果错误。
- 基本类型数组(int[]、double[] 等)不支持 Comparator,也不能用包装类 key 去查(如用 Integer 查 int[])
- 对象数组(Integer[]、String[] 等)要求元素实现 Comparable,或显式传入 Comparator;Comparator 必须与排序时一致
- null 值在基本类型中不存在,在对象数组中可能触发 NullPointerException(取决于 Comparator 是否处理 null)
- 子区间查找可用 binarySearch(arr, fromIndex, toIndex, key),适用于分段处理或跳过无效区域











