Collections.binarySearch本身不提升性能,仅当列表升序、排序与查找用同一比较逻辑、容器支持随机访问时才发挥O(log n)效率;否则结果不可信或退化为O(n log n)。

Collections.binarySearch 本身不提升性能,它只是在条件满足时才释放 O(log n) 的潜力。真正决定性能的,是你是否提前做好了三件事:列表必须升序排好、排序和查找用同一个比较逻辑、容器支持快速随机访问。
排序必须严格升序,且不可跳过
binarySearch 不检查顺序,也不帮你排序。传入降序、部分乱序或未排序的 List,结果完全不可信。
- 对 Integer、String 等天然有序类型,调用 Collections.sort(list) 即可
- 对自定义对象(如 Person),排序和查找必须复用同一个 Comparator 实例,不能只写语义相同的 lambda —— 每次 new Comparator 都是不同对象
- 避免用 list.stream().sorted().collect(Collectors.toList()),这生成的是新列表,原列表仍是乱的
返回值要直接用,别手算插入点
返回值不是布尔信号,而是带位置信息的整数:
- ≥ 0:找到,数值就是真实索引
- < 0:没找到,插入位置 = -result - 1(不是 Math.abs(result) - 1)
- 例如返回 -4,插入点就是 3;返回 -1,插入点是 0;返回 -6(列表长度为 5),插入点是 5
- 这个插入点始终落在 [0, list.size()] 范围内,可直接用于 list.add(insertIndex, e)
选对容器,避开性能陷阱
binarySearch 效率依赖随机访问能力,不是所有 List 都适用:
立即学习“Java免费学习笔记(深入)”;
- 只支持 List,不支持 Set、Collection 或数组(int[] 不行,必须用 Integer[] 再经 Arrays.asList() 包装)
- 优先用 ArrayList;LinkedList 表面能调用,但内部 get(i) 是 O(n),整体退化为 O(n log n),比线性遍历还慢
- 列表含 null 时,Comparator 必须显式处理(如 Comparator.nullsFirst(Comparator.naturalOrder())),否则抛 NullPointerException
高频场景下注意并发与泛型安全
一次排序、多次查找是最优使用模式。若数据频繁变更,需额外防护:
- 排序后到查找前,若有其他线程修改列表,结果不保证正确 —— 推荐把“排序 + 查找”封装成原子操作,或转用不可变列表(如 Guava 的 ImmutableList)
- 禁止用原始类型声明,如 List list = new ArrayList(),混入不同类型元素会在运行时抛 ClassCastException
- 自定义类的 compareTo 或 Comparator 必须满足自反性、传递性、一致性,且无副作用



















