HashSet和TreeSet的equals判断逻辑不同:HashSet依赖hashCode()和equals(),TreeSet依赖compareTo()或Comparator;List类按索引顺序比较;CollectionUtils.isEqualCollection做频次一致的多重集比较。

HashSet 和 TreeSet 的 equals 判断逻辑完全不同
Java 中集合的 equals 不是看“内容是否一样”,而是看“是否满足该集合定义的相等语义”。HashSet 依赖 hashCode() + equals(),而 TreeSet 依赖 compareTo() 或 Comparator 的顺序一致性。
-
HashSet<String>和HashSet<String>比较时,只要元素相同、顺序无关,就返回true -
TreeSet<String>和TreeSet<String>比较也只看元素,不看插入顺序 —— 因为它本就没有顺序概念,只有排序后结构 - 但如果你用自定义类且没重写
compareTo(),或Comparator返回结果不稳定(比如比较中用了随机数),TreeSet.equals()可能返回false即使元素完全一样 - 更隐蔽的是:两个
TreeSet如果用了不同的Comparator(哪怕逻辑等价),它们的equals()一定返回false—— 因为 JDK 明确要求comparator()方法返回值也必须相等
ArrayList 和 LinkedList 的 equals 看顺序,不是看“有没有”
这两个是 List 接口实现,equals 是严格按索引比对的:长度相同、每个位置的元素都 equals 才算相等。这和 Set 完全不同。
-
Arrays.asList("a", "b")和Arrays.asList("b", "a")调用equals()返回false - 哪怕你把
LinkedList转成ArrayList再比,只要顺序不同,还是false - 空集合之间可以安全比较:
new ArrayList<>().equals(new LinkedList<>())是true - 注意:如果元素是自定义对象,它们的
equals必须正确实现,否则整条链路都会失效
使用 CollectionUtils.isEqualCollection 前先看清它在做什么
Apache Commons Collections 的这个工具方法常被误认为是“无视顺序的 List 相等判断”,但它其实做的是**多重集(multiset)比较**:两个集合含有的每个元素频次一致即为相等,不关心顺序,也不去重。
-
isEqualCollection([1,1,2], [1,2,2])→false(前者有两个 1,后者有两个 2) -
isEqualCollection([1,2,2], [2,1,2])→true(频次一致) - 它内部会调用
getCardinality统计频次,对大集合性能较差;小数据没问题,大数据建议改用Map<E, Integer>手动统计 - 它不处理
null元素的安全问题:如果集合里有null,且元素类型没重写equals,可能抛NullPointerException
别直接用 == 或没重写的 equals 比自定义对象集合
这是最常踩的坑:你以为在比内容,其实只是在比引用或默认的内存地址。
立即学习“Java免费学习笔记(深入)”;
- 如果你的
User类没重写equals和hashCode,那么两个字段完全一样的User实例,在HashSet里会被当作不同元素,在equals比较时也返回false -
ArrayList<User>里的equals会逐个调用User.equals(),如果没重写,就是Object.equals()—— 等价于== - Lombok 的
@EqualsAndHashCode默认不包含static或transient字段,如果关键 ID 是transient,生成的equals就不可靠 - IDEA 自动生成的
equals如果漏选了某个业务关键字段(比如status),测试可能通过,线上却出错










