Arrays.binarySearch不是简单二分查找,而是优化实现:小数组线性扫描、大数组防溢出二分,要求数组严格升序,否则结果未定义;返回≥0为索引,<0时-(返回值+1)为插入点。

Arrays.binarySearch 不是让你“实现”二分查找,而是直接调用一个已优化的查找逻辑——它在小数组上走线性扫描,大数组才启用防溢出的二分流程,前提是数组必须升序排列,否则结果未定义。
必须先排序,且排序与查找逻辑要一致
binarySearch 本身不检查数组是否有序,也不做任何预处理。传入乱序数组,返回值既不是正确索引,也不符合插入点规则,而且不会报错,只会静默返回不可靠结果。
- 基本类型数组(如 int[]):调用 Arrays.sort(arr) 升序排序后才能安全使用
- 对象数组(如 String[] 或自定义类):元素需实现 Comparable,或显式传入 Comparator
- 若数组需保持原顺序,应先 Arrays.copyOf(arr, arr.length) 复制再排序
- 降序数组不能直接用:改用 Arrays.binarySearch(arr, key, Collections.reverseOrder())
准确理解返回值,别只看是不是 -1
返回值不是布尔标识,而是一个带位置语义的整数:
- ≥ 0:表示找到,数值就是该元素在数组中的索引(例如返回 2,说明 key 在第 3 个位置)
- < 0:表示未找到,此时 -(返回值 + 1) 就是插入点(即维持升序时 key 应放的位置)
- 判断是否存在,必须写 result >= 0,而不是 result != -1(因为未找到可能返回 -2、-5 等)
- 快速还原插入点:可用 int pos = ~result(按位取反),比如 result = -4 → pos = 3
支持区间查找和浮点数等特殊场景
binarySearch 提供四参数重载,可用于局部搜索;对 double 等浮点类型,内部使用 Double.doubleToLongBits() 做位级比较,确保 NaN 和 ±0.0 行为一致。
- 查子区间:Arrays.binarySearch(arr, fromIndex, toIndex, key),范围是 [fromIndex, toIndex)(右边界不包含)
- 区间内未找到时,插入点基于该子区间计算:若 key 小于所有元素,返回 -(fromIndex + 1)
- 浮点查找务必保证排序与查找用同一比较逻辑;业务敏感场景(如金融)建议转为 long 或 BigDecimal 处理
- 含 null 的对象数组,若没传 Comparator,运行时可能抛 NullPointerException
哪些情况不该用 binarySearch
它高效,但有明确适用边界。超出这些条件,强行使用反而引入隐患或性能倒退。
- List(尤其是 LinkedList):binarySearch 只接受数组;查 List 应用 Collections.binarySearch,且仅推荐用于 ArrayList
- 频繁增删的数据:每次变动后重排序成本高,优先考虑 TreeSet / TreeMap
- 需要最左/最右重复位置:binarySearch 不保证返回边界下标,需手写二分或配合线性扩展
- 旋转数组、部分有序、自定义非单调结构:不属于标准二分前提,需单独设计查找逻辑

















