collections.binarysearch将查找降至o(log n)的前提是列表已排序且排序与查找使用同一comparator,仅适用于randomaccess列表(如arraylist),返回值编码存在性与插入位置。

想用 Collections.binarySearch 把查找从 O(n) 降到 O(log n),关键不在“怎么调用”,而在于“能不能安全调用”。它不排序、不校验、不兜底,只在你把前提全备好之后,才给出精准结果。
必须先排好序,且只排一次
binarySearch 不检查顺序,也不帮你排序。传入未排序或部分错乱的列表,返回值完全不可信——可能漏掉真实存在的元素,也可能返回错误正索引。
- 升序场景:初始化时调用
Collections.sort(list)(自然序)或list.sort(comparator)(自定义序),后续所有查找复用该列表 - 避免每次查找前都重排,否则总代价退化为 O(n log n),比线性扫描还慢
- 若需动态插入新元素,用 binarySearch 找到插入位置(处理负数返回值),再调用
list.add(insertIndex, item)维持有序,而不是全量重排
排序和查找必须用同一个 Comparator
不是“逻辑相同”,而是引用一致或语义等价。Lambda 每次调用都生成新对象,两次写 Comparator.comparing(String::length) 实际是两个不同实例。
- 推荐定义为
static final字段复用,例如:public static final Comparator<string> BY_LENGTH = Comparator.comparing(String::length);</string> - 排序时:
list.sort(BY_LENGTH);
查找时:Collections.binarySearch(list, "abc", BY_LENGTH); - 用自然序(如
String、Integer)可不传 Comparator;一旦传了,就必须和排序所用完全一致
只对支持随机访问的 List 有效
binarySearch 内部高频调用 get(i),要求该操作是 O(1)。ArrayList 满足,LinkedList 不满足——取中间节点需遍历,单次 get(mid) 就是 O(n),整体退化为 O(n log n)。
- 优先用
ArrayList或Arrays.asList()包装的固定列表 - 运行时可用
list instanceof RandomAccess判断,不满足就别硬上 binarySearch - 数组必须用包装类型(如
Integer[]),再经Arrays.asList()包装;int[]不支持
正确解读返回值,直接提取位置信息
返回值不是布尔信号,而是带语义的整数编码,能同时回答“是否存在”和“该插在哪”:
- ≥ 0:找到,数值就是目标元素的索引(重复元素时返回任意一个匹配位置)
- -result - 1(不是
Math.abs(result) - 1,也不是~result)
例如返回-4,插入点是3;返回-1,插入点是0;返回-6(列表长度为 5),插入点是5(末尾之后) - 这个插入点始终落在
[0, list.size()]范围内,可直接用于list.add(insertIndex, e)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











