Collections.binarySearch仅适用于已排序且支持随机访问的List,需用同一Comparator排序与查找,返回值兼具查找结果与插入位置信息。

Collections.binarySearch 不是“拿来就用”的查找函数,它只对已排序、结构适配、比较一致的 List 才真正高效。用错前提,结果不可信,性能还可能更差。
必须先排序,且只排一次
binarySearch 从不排序,也不验证顺序。它直接按二分逻辑读取中间位置——如果列表乱序,返回值毫无意义。
- 初始化时调用
Collections.sort(list)或list.sort(comparator)完成升序排序 - 避免每次查找前都调用 sort:那样总代价是 O(n log n),比线性扫描还慢
- 若需动态插入新元素,用 binarySearch 返回值算出插入点(
-result - 1),再list.add(index, item)维持有序,而不是全量重排
Comparator 必须完全一致
排序和查找用的 Comparator 不仅逻辑要相同,最好还是同一个实例——Java 不做语义推断,只机械执行二分。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- Lambda 表达式每次调用都生成新对象,
Comparator.comparing(String::length)写两次就是两个不同实例 - 推荐定义为
public static final Comparator<String> BY_LENGTH = Comparator.comparing(String::length);,复用同一引用 - 自然序(如 String、Integer)可不传 Comparator;一旦传了,就必须和排序所用完全一致
- null 值需显式处理,例如用
Comparator.nullsFirst(),否则运行时抛 NullPointerException
只适用于 RandomAccess 列表
binarySearch 内部高频调用 get(int),必须保证 O(1) 随机访问能力,否则性能急剧退化。
立即学习“Java免费学习笔记(深入)”;
- 优先使用 ArrayList —— 实现 RandomAccess,get 是常数时间
- 绝对避免在 LinkedList 上调用:get(i) 是 O(n),整体会退化为 O(n log n),十万级数据可能比 ArrayList 线性扫描还慢 10 倍
- 可用
list instanceof RandomAccess提前判断,不满足就别硬上
正确解读返回值,不止是“找没找到”
返回值携带双重语义:既是查找结果,也是位置线索。
- ≥ 0:找到,数值即元素索引
- 负数:未找到,插入点为
-result - 1(例如返回 -4,插入点是索引 3) - 不要用
result == -1判断“不存在”——-1 只表示应插在开头(索引 0),比如查 0 在 [1,2,3] 中就返回 -1 - 该插入点可直接用于
list.add(-result - 1, target),适合构建轻量级有序缓存

















