Arrays.binarySearch仅适用于已排序数组,时间复杂度O(log n),返回值≥0表示存在并给出索引,负数表示未找到且编码插入点;使用前须确保排序,重复元素不保证边界位置,对象数组需指定Comparator或实现Comparable。

Arrays.binarySearch 是 Java 中用于在已排序数组中快速定位元素的标准工具,它不排序、只检索,性能稳定在 O(log n),但前提是数组必须已按升序排列;一旦忽略排序前提,结果完全不可靠。
必须先排序,否则结果无意义
binarySearch 本身不做任何排序检查,也不会报错。传入未排序数组时,返回值既不是正确索引,也不符合插入点规则——它只是在“假装有序”的前提下走完二分逻辑,结果纯属巧合。
- 调用前务必确保数组已排序,推荐使用 Arrays.sort()(基本类型)或 Arrays.sort(arr, comparator)(对象数组)
- 若原始顺序需保留,可复制数组再排序:int[] sorted = arr.clone(); Arrays.sort(sorted);
- 高频查找场景建议在初始化或数据写入后一次性排序,避免每次检索都 sort —— 那会把 O(log n) 拉回 O(n log n)
返回值不是简单的“找到/没找到”
它返回的整数同时承载位置信息和插入语义:≥ 0 表示存在且给出索引;负数则编码了“该插哪儿”,计算公式为:插入点 = -(返回值 + 1)。
- 查 25 在 [10,20,30,40] 中 → 返回 -3 → 插入点 = -(-3 + 1) = 2,即放在索引 2(20 和 30 之间)
- 查 -5 → 返回 -1 → 插入点 = 0,应插最前
- 查 50 → 返回 -5 → 插入点 = 4,即数组末尾后一位(索引等于数组长度)
- 这个设计让上层能轻松实现“查找+插入”逻辑,比如维护有序列表时直接用该值做 insert
重复元素与自定义类型要特别留心
当数组含重复值时,binarySearch 只保证返回“某个匹配位置”,不保证是第一个或最后一个;对非基本类型,比较逻辑必须明确。
- 要找左边界(首个等于 key 的位置),不能依赖 binarySearch 结果,需额外向左线性扫描,或改用手写二分(控制 high = mid)
- String[] 按长度查找:Arrays.binarySearch(arr, "xx", Comparator.comparing(String::length))
- 自定义类必须实现 Comparable,或每次传 Comparator;含 null 元素时,Comparator 必须显式支持 null,否则抛 NullPointerException
- int[] 和 Integer[] 不互通:前者走基本类型重载,后者走对象版,混用可能引发装箱异常或逻辑偏差
别为了“存在性判断”滥用 binarySearch
如果只需要知道元素在不在,而不是它的位置,用 binarySearch 反而绕路——尤其小数组或低频场景。
- 简单判断存在:Arrays.stream(arr).anyMatch(x -> x == key) 更直观(注意引用 vs 值比较)
- 但 stream 方式是 O(n),大数据量或高频调用仍应坚持排序 + binarySearch 路线
- 若业务需频繁增删查,考虑 TreeSet 或 TreeMap,它们内部自动维持有序,add/contains 均为 O(log n)


















