Arrays.binarySearch 的性能优势仅在数组已排序且多次复用时体现,它不排序、不校验、不处理 null;必须预先排序,正确选择重载方法,准确解读返回值,动态场景应选用 TreeSet 等更合适结构。

Arrays.binarySearch 的性能优势只在数组已排序且多次复用时真正体现出来。它本身不排序、不校验、不处理 null,快的前提是“你已经把前提做对了”。
必须先排序,但别每次都排
binarySearch 不负责排序,只做查找。传入未排序数组,结果完全不可信——可能返回错误正数索引,也可能返回任意负值,毫无规律可言。
- 首次使用前调用 Arrays.sort(arr)(基本类型)或 Arrays.sort(arr, comparator)(对象数组),确保升序
- 同一数组需多次查找时,排序只需一次;反复 new 数组 + 排序,IO 和创建开销远超查找本身
- 数据来自数据库时,优先在 SQL 层加 ORDER BY id ASC,避免 Java 层重复排序
选对重载方法,避开装箱和类型陷阱
int[] 和 Integer[] 调用的是完全不同的重载,混用会导致编译失败或运行时异常。
- 工号、ID 等纯数字场景,用 int[] + Arrays.binarySearch(int[], int),零装箱、无 null 风险
- 若必须用 Integer[],确保所有元素非 null,且 key 用 Integer.valueOf(x) 显式构造
- 字符串按长度查?用 Arrays.binarySearch(strArr, key, Comparator.comparing(String::length)),但排序时也得用同一 Comparator
正确解读返回值,别用 == -1 判断
返回值不是布尔标识,而是带位置语义的整数:≥ 0 是真实索引,负数编码插入点。
- 判断是否存在,只写 index >= 0;写 index != -1 会漏掉索引 0 和其他负值情况
- 需要插入位置?直接算 -(index + 1),比如返回 -4 → 插入点是 3
- 想快速还原插入点,可用位运算:int pos = ~index(等价于 -(index + 1))
高频场景建议封装或换结构
如果数组频繁增删、多线程读写,或不确定是否始终有序,binarySearch 就不再是最优解。
- 动态数据优先考虑 TreeSet 或 TreeMap,自动维护有序 + O(log n) 查找
- 需保留插入顺序又常查?用 LinkedHashSet 配合手动维护有序列表
- 并发更新场景下,避免直接共享数组;可用 volatile 引用 + 双重检查更新,或改用 CopyOnWriteArrayList(仅适合读远多于写的场景)


















