Java中使用ArrayList的indexOf方法查找类指定字段对应元素索引问题
关于ArrayList中按类字段匹配调用indexOf的问题解答
问题核心原因
ArrayList.indexOf()方法的匹配逻辑完全依赖元素的equals()方法实现,默认继承自Object的equals()方法仅比较对象的内存地址,即使两个Contact实例的id字段完全一致,只要是不同的对象实例,indexOf也会返回-1,这就是你现在返回结果不符合预期的根本原因。
可选解决方案
方案1:继续使用ArrayList,无需更换数据结构
如果除按id查索引外,ArrayList的其他特性都能满足你的需求,优先选这个方案,有两种实现方式:
- 重写Contact类的
equals()和hashCode()方法,匹配逻辑绑定id字段
示例代码如下:
重写完成后,你构造一个id为目标值的Contact实例,传入import java.util.Objects; public class Contact { private Long id; // 其他字段省略 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Contact contact = (Contact) o; return Objects.equals(id, contact.id); } @Override public int hashCode() { return Objects.hash(id); } // getter、setter省略 }indexOf()即可得到正确索引,找不到会返回-1,和原生方法行为一致。注意:如果你的业务场景中还有其他需要判断Contact相等的逻辑,且判断规则不是仅看id,不建议用这个方案,会影响其他场景的equals判断结果。
- 手动遍历ArrayList匹配id,无需修改原有类逻辑
Java 8及以上版本可以用IntStream快速实现:
低版本Java直接用for循环遍历即可,逻辑和上述代码一致。// 假设contactList是你的ArrayList<Contact>实例,targetId是你要匹配的id值 int targetIndex = IntStream.range(0, contactList.size()) .filter(i -> Objects.equals(contactList.get(i).getId(), targetId)) .findFirst() .orElse(-1);
方案2:高频查询场景下可更换数据结构
如果你需要非常频繁的执行按id查询的操作,ArrayList单次遍历的时间复杂度为O(n),数据量较大时性能会明显下降,这种场景可以考虑更换为:
HashMap<Long, Contact>:key存储id,value存储Contact实例,按id查询的时间复杂度为O(1),缺点是不保留元素的插入顺序LinkedHashMap<Long, Contact>:保留插入顺序的同时支持O(1)按id查询,是兼顾有序和查询性能的选择
内容的提问来源于stack exchange,提问作者Larry Arndt
相关产品推荐
相关产品推荐

