ArrayList 的 indexOf 方法需确保元素类型正确且自定义类重写 equals() 和 hashCode(),否则返回 -1;它只返回首个匹配索引,不支持起始位置参数,性能上 ArrayList 优于 LinkedList。

indexOf 在 ArrayList 中怎么用才不会返回 -1
Java 的 indexOf 方法只在 ArrayList、LinkedList 等实现了 List 接口的集合中可用,它不是 Set 或 Map 的方法。调用前必须确认集合类型,否则编译不通过。
常见错误是传入一个未重写 equals() 的自定义对象——indexOf 内部靠 equals() 判断相等,若没重写,哪怕两个对象字段完全一样,也会因引用不同而返回 -1。
- 确保目标元素与集合中元素满足
equals()为true(对字符串、包装类等默认 OK) - 对自定义类,必须同时重写
equals()和hashCode() -
indexOf只返回第一个匹配项的索引,查不到就返回-1,不抛异常
示例:
ArrayListlist = new ArrayList<>(Arrays.asList("a", "b", "c", "b")); int idx = list.indexOf("b"); // 返回 1,不是 3
String 的 indexOf 和 List 的 indexOf 完全不是一回事
别被同名误导:字符串的 indexOf(char)、indexOf(String) 是查找子串/字符位置;而 List.indexOf(Object) 是查找“集合中首次出现该对象的下标”。两者语义不同、参数类型不同、底层实现也不同。
关键区别:
立即学习“Java免费学习笔记(深入)”;
- 字符串
indexOf支持起始位置参数(如str.indexOf("x", 5)),List 没有这个重载 - 字符串返回的是字符偏移量(从 0 开始),List 返回的是元素下标(也是从 0 开始,但概念不同)
- 字符串可查
char或String,List 只能查Object,且依赖equals
误用典型:
String s = "hello";
s.indexOf('l'); // ✅ 返回 2
ArrayList nums = Arrays.asList(1, 2, 3);
nums.indexOf(2); // ✅ 返回 1
nums.indexOf('2'); // ❌ '2' 是 char,自动装箱为 Integer.valueOf(50),肯定找不到
为什么在 LinkedList 上用 indexOf 性能差
LinkedList 的 indexOf 时间复杂度是 O(n),而且比 ArrayList 更慢——因为它是链表结构,每次访问元素都要从头逐个 next,无法像数组那样直接计算内存偏移。
如果你频繁按值查索引,又用的是 LinkedList,说明数据结构选错了。除非你同时大量做插入/删除中间节点操作,否则应优先用 ArrayList。
- 查索引频次高 → 用
ArrayList - 需要频繁在任意位置增删,且基本不查索引 → 才考虑
LinkedList - 如果既要快速查又要快速删,考虑用
LinkedHashSet+ 额外维护索引映射,或换用第三方库如 Trove
替代方案:什么时候不该用 indexOf
当你要找多个匹配项、或需要连带获取元素本身、或想避免线性扫描时,indexOf 就不是最优解。
更合适的做法:
- 遍历 +
for(int i = 0; i ,边查边记索引,一次拿到所有匹配位置 - 用
IntStream.range(0, list.size())+filter(Java 8+),函数式写法更清晰 - 对固定集合且查询密集,预先构建
Map(仅限元素唯一) - 用
Collections.binarySearch前提是已排序且实现了Comparable,比indexOf快但限制多
最容易被忽略的一点:indexOf 查的是“值相等”,不是“引用相等”;而很多人调试时用 == 检查结果,导致误判逻辑错误。










