Collections.binarySearch要求列表必须预先按同一规则升序排序,否则结果不可靠;它不排序、不校验、不处理降序,对自定义对象需用Comparator统一排序与查找规则。

要用 Collections.binarySearch 在有序 List 中快速定位元素,关键不是“能不能用”,而是“怎么用才不翻车”。它本身不排序、不校验、不兜底——只在你确保一切就绪后,给出一个精准下标或插入点。
必须提前升序排序,且排序与查找用同一规则
binarySearch 不会帮你排序,也不识别降序。哪怕列表只差一个元素位置错乱,结果就完全不可信。
- 对 String、Integer 等天然可比类型,调用 Collections.sort(list) 即可
- 对自定义对象(如 Person),必须先用 Comparator 排序,再用查找
- 别写 list.stream().sorted().collect() —— 那生成的是新 List,原 list 还是乱的
返回值不是“失败信号”,而是插入位置编码
查不到时返回负数,不是报错,而是设计用来告诉你该插哪儿。
- 返回值 ≥ 0:表示找到,数值就是索引
- 返回值为负(如 -4):表示没找到,应插入的位置是 -(-4) - 1 = 3
- 安全写法:直接用 int insertionPoint = -pos - 1,不用手算
- 插入点一定在 [0, list.size()] 范围内:0 表示最前,list.size() 表示追加到最后
类型和容器匹配有硬性限制
看着简单,踩坑多在细节。
- 只能用于 List,不能传 Collection 或 Set
- 数组要先用 Arrays.asList(arr) 包装,但 arr 必须是包装类型(Integer[] 可以,int[] 不行)
- 列表含 null 时,Comparator 必须显式支持 null 比较,否则运行时报 NullPointerException
- 别在 LinkedList 上硬用 —— 它的 get(i) 是 O(n),binarySearch 内部靠随机访问,实际退化成慢查找
并发与数据稳定性需额外考虑
即使刚排完序,查的时候列表可能已被其他线程修改。
- binarySearch 是纯读操作,但不提供同步保障
- 若列表频繁被修改,建议改用 TreeSet 或带索引结构
- 对只读或低频更新的 ArrayList / Arrays.asList 固定列表,binarySearch 效果最佳

















