如何基于手机号移除ArrayList中重复的PhoneContactsModel对象?
问题排查与解决方案
咱们先拆解你遇到的两个核心问题:TreeSet去重失效和HashSet未生效,逐个分析原因并给出可落地的修复方案。
1. TreeSet去重失效的根源:Comparator实现不符合规范
你自定义的Comparator存在逻辑漏洞:TreeSet依赖Comparator的返回值判断元素是否相等,规范要求如果a.compare(b) == 0,必须满足b.compare(a) == 0;如果a.compare(b) > 0,则b.compare(a) < 0。
但你的实现里,只要手机号不相等就返回1,这会让TreeSet误以为A和B、B和A都是不同元素,导致重复项无法被识别。
修复后的TreeSet去重代码
可以用Java 8的Comparator.comparing简化实现,同时保证逻辑合规:
public ArrayList<PhoneContactsModel> removeDuplicates(ArrayList<PhoneContactsModel> list) { // 按手机号忽略大小写比较,同时处理null场景 Set<PhoneContactsModel> set = new TreeSet<>(Comparator.comparing( PhoneContactsModel::getContactNumber, (s1, s2) -> { if (s1 == null && s2 == null) return 0; if (s1 == null) return -1; if (s2 == null) return 1; return s1.compareToIgnoreCase(s2); } )); set.addAll(list); return new ArrayList<>(set); }
2. HashSet去重未生效的可能原因及修复
你已经重写了equals和hashCode,按道理HashSet应该能正常去重,没生效大概率是这几个问题:
- 手机号格式不一致:比如有的带
+86前缀、有的带空格/连字符,导致equals判断不相等 - equals方法未处理null:如果某个对象的
contactNumber为null,直接调用equals会抛空指针,也无法正确比较null场景 - 代码执行逻辑问题:比如没有把HashSet的结果重新赋值给目标列表
第一步:完善equals和hashCode方法
先补上null处理,同时支持忽略大小写(如果业务需要):
@Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof PhoneContactsModel)) return false; PhoneContactsModel that = (PhoneContactsModel) o; // 处理null场景,同时忽略大小写比较手机号 if (contactNumber == null) { return that.contactNumber == null; } return contactNumber.equalsIgnoreCase(that.contactNumber); } @Override public int hashCode() { // 保证忽略大小写的手机号hashCode一致,同时处理null return contactNumber == null ? 0 : contactNumber.toLowerCase().hashCode(); }
第二步:HashSet去重代码
public ArrayList<PhoneContactsModel> removeDuplicates(ArrayList<PhoneContactsModel> list) { Set<PhoneContactsModel> set = new HashSet<>(list); return new ArrayList<>(set); }
额外优化:保留元素插入顺序
如果你的需求是保留列表中第一个出现的重复元素,而不是TreeSet排序后的结果,推荐用LinkedHashSet——它既能去重,又能严格保持元素的插入顺序:
public ArrayList<PhoneContactsModel> removeDuplicates(ArrayList<PhoneContactsModel> list) { Set<PhoneContactsModel> set = new LinkedHashSet<>(list); return new ArrayList<>(set); }
内容的提问来源于stack exchange,提问作者basha
相关产品推荐
相关产品推荐

