集合中Comparable接口和Equals方法的冲突
equals方法是在讲解集合的时候讲到的,因为集合的特点是,无序,不重复,无索引,LinkedHashSet有序是因为,它的底层是通过双向链表和哈希表共同完成的。通过双向链表来获取第一个第二个元素。从而保证添加顺序和遍历的顺序是一样的。
HashSet和LinkedHashSet保证存储元素不重复的方法是通过equals方法。
而TreeSet保证元素不重复的方法是通过。比较方法,即Comparable或Comparator
矛盾分析
举个例子
如果说我只按照总分来排序,那么在遇到总分一样,而其他属性不一样的时候,它是怎么排序的?
如果使用TreeSet或TreeMap(它们基于红黑树),当比较结果为0时,会认为两个对象相等,那么后添加的元素会替换掉前面的(在Set中不会添加重复元素,在Map中会覆盖值)。
核心问题:TreeSet
使用 compareTo()
判断元素是否相等,而其他集合(如 HashSet
)使用 equals()
。当这两种方法对"相等"的定义不一致时,会导致:
同一对象在不同集合中被判定为不同
违反 Set 接口的基本契约(不允许重复元素)
会导致破坏 Set 契约:
- Set 应包含唯一元素
- 当
compareTo()
返回 0 但equals()
返回 false 时,TreeSet
会错误地拒绝添加本应不同的元素
解决方案
保持一致性
确保 compareTo()
与 equals()
对相等的定义一致:
@Override
public int compareTo(Product other) {// 使用与 equals() 相同的字段组合int result = this.id.compareTo(other.id);if (result == 0) {result = this.name.compareTo(other.name);}return result;
}
一定能通过各种属性判断,区分出两个对象,从而不会出现误判现象