如何在存储自定义类对象的ArrayList中使用contains方法仅按id检索
解决方案
List.contains() 方法的匹配逻辑完全依赖元素的equals()方法实现,默认是比较对象的内存地址,要实现按id字段检索,有三种常用实现方式:
方案1:重写Test类的equals()和hashCode()方法(可直接使用contains)
如果业务场景中Test类的相等判断默认就是按id匹配,直接修改类的equals规则即可:
public class Test { private int id; private String name; private int age; public Test(int id, String name, int age) { this.id = id; this.name = name; this.age = age; } // 新增id的getter方法 public int getId() { return id; } // 重写equals仅对比id字段 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Test test = (Test) o; return id == test.id; } // 重写hashCode仅基于id生成,和equals规则保持一致 @Override public int hashCode() { return Integer.hashCode(id); } }
使用方式:
// 直接构造id为4的Test对象传入contains即可 boolean isId4Exist = list.contains(new Test(4, null, 0));
方案2:使用Stream API(无需修改原类,业务代码无显式循环)
如果只是这一处需要按id判断,其他场景还要用原有的相等逻辑,推荐用Java 8及以上的Stream流实现,不需要自己写循环代码:
// 注意需要先给Test类加上id的getter方法getId() boolean isId4Exist = list.stream().anyMatch(test -> test.getId() == 4);
这个方案底层依然会遍历列表,但遍历逻辑由JDK实现,业务侧不需要手动写循环代码,灵活度更高。
方案3:提前转Map(适合频繁判断的场景)
如果需要大量做这类id存在性判断,可以提前把列表转成id为key的Map,后续判断的时间复杂度为O(1),性能更高:
Map<Integer, Test> testMap = list.stream().collect(Collectors.toMap(Test::getId, Function.identity())); boolean isId4Exist = testMap.containsKey(4);
内容的提问来源于stack exchange,提问作者Taha Sami
相关产品推荐
相关产品推荐

