Arrays.binarySearch是Java中专为已排序升序数组设计的O(log n)查找工具,返回值≥0表示找到并给出下标,<0则-(返回值+1)为插入点,误用于未排序数组结果不可信。

Arrays.binarySearch 是 Java 中唯一专为已排序数组设计的 O(log n) 查找工具,不是通用搜索函数,也不是自动排序器。用对场景,它比遍历快百倍;用错前提,结果完全不可信。
必须先排序,且只认升序
binarySearch 不检查数组是否有序,也不做任何排序。传入未排序数组,返回值无逻辑可言——可能碰巧是正数(误判存在),也可能返回任意负数(插入点失效)。
- 基础类型数组:调用 Arrays.sort(arr) 一次即可,后续所有查找复用
- 不想改原数组?用 arr.clone() 复制后再排序
- 降序需求?不能直接用,要显式传 Comparator,例如 Collections.reverseOrder()
- 开发阶段建议加简单校验:for (int i = 1; i < arr.length; i++) if (arr[i] < arr[i-1]) throw new IllegalStateException("unsorted")
读懂返回值:索引和插入点是一体两面
返回值不是布尔量,而是携带位置语义的整数:
- ≥ 0:找到,数值就是元素在数组中的实际下标(从 0 开始)
- < 0:未找到,此时 -(返回值 + 1) 就是插入点索引
- 例如返回 -4 → 插入点是 3;返回 -1 → 插入点是 0;返回 -7(数组长为 6)→ 插入点是 6(末尾)
- 判断“是否存在”必须写 result >= 0,别用 != -1 —— 那只是插入点为 0 的一种情况
实用场景不止是“找得到吗”
利用插入点信息,能做不少轻量级数据操作:
- 快速分档定位:比如已排序的响应时间分位点 [50, 120, 280, 550],查 200ms 耗时返回 -3 → 插入点是 2 → 属于第 2–3 档之间
- 维护有序缓存:调用后得插入点,再用 System.arraycopy 移位插入,比遍历找位置快得多
- 区间计数:查下界值的插入点 A 和上界值的插入点 B,差值 B - A 就是该区间内元素个数
- 去重统计:先排序,再用 binarySearch 找到某值位置,向左/右线性探查边界,算出重复次数
避开高频陷阱
这些错误看似低级,但上线后极难排查:
- 混用数组类型:int[] 不能传给 Object[] 版本,编译可能通过但运行逻辑崩溃
- null 值雷区:对象数组含 null,又没用 null-safe Comparator,直接抛 NullPointerException
- 浮点数 NaN:NaN 不参与有效比较,排序和查找都会出问题
- 误用于 List:ArrayList 要用 Collections.binarySearch(list, key);LinkedList 效率极低,不建议
- 动态数据硬套:频繁增删就别用数组+binarySearch,改用 TreeSet 或 TreeMap 更稳妥

















