Collections.binarySearch是严格依赖前提的精准定位器:必须先升序排序,使用同一Comparator实例,返回值含位置语义(≥0为索引,<0时插入点=-result-1),仅适用于ArrayList等支持O(1)随机访问的List。

Collections.binarySearch 不是“一调就灵”的黑盒工具,而是严格依赖前提的精准定位器。它只在你把排序、类型、比较逻辑全部对齐后,才返回一个真正可用的索引或插入位置。
必须先升序排序,且不能跳过这步
binarySearch 从不排序,也不检查顺序。传入乱序列表,结果完全不可信——哪怕只有一个元素错位,查找就可能失败或偶然命中,但无法复现。
- 对 String、Integer 等天然有序类型:调用 Collections.sort(list) 即可,这是最常用也最安全的方式
- 对自定义对象(如 Person):必须用同一个 Comparator 实例 先排序、再查找,不能只是“逻辑相同”
- 避免写 list.stream().sorted().collect(Collectors.toList()) ——那生成的是新 List,原 list 仍是乱的,查的还是错的
返回值不是布尔信号,而是位置语义
它返回的不是“找到了”或“没找到”,而是一个带明确含义的整数:
- ≥ 0:表示目标存在,数值就是它在 List 中的真实下标(从 0 开始)
- < 0:表示未找到,但负数里藏着插入点——插入位置 = -result - 1
- 例如返回 -4,插入点是 3;返回 -1,插入点是 0;返回 -6(列表长度为 5),插入点是 5(即末尾之后)
- 这个插入点始终落在 [0, list.size()] 范围内,可直接用于 list.add(insertIndex, key)
容器类型和运行环境很关键
表面能调用,不代表真高效;看似简单,细节决定成败:
- 只接受 List,不支持 Set、Collection 或原始数组;基本类型数组(如 int[])需改用 Arrays.binarySearch
- 优先用 ArrayList;LinkedList 上慎用——其 get(i) 是 O(n),整个 binarySearch 会退化为 O(n log n),比遍历还慢
- 列表含 null 时,Comparator 必须显式支持(如 Comparator.nullsFirst()),否则抛 NullPointerException
- 并发场景下,即使刚排完序,查找过程中列表被其他线程修改,结果就不保证可靠
自定义对象查找要严守一致性
排序和查找的比较逻辑必须来自同一个 Comparator 实例,不能靠“感觉一样”:
- 错误示范:用 Comparator.comparing(String::toLowerCase) 排序一次,再用同样写法查找一次——每次 lambda 都新建对象,等于用了两个不同 Comparator
- 正确做法:定义为 static final Comparator<String> CI_COMP = String.CASE_INSENSITIVE_ORDER; 并复用
- 自定义类的 compareTo 或 Comparator 必须满足自反性、传递性、一致性,且无副作用
- 禁止用原始类型(raw type)声明列表,如 List list = new ArrayList();,混入不同类型会导致运行时 ClassCastException

















