等于和可比较集

我在这里发布了一些代码,正确解决了海报的问题。 OP希望删除重复项并将某些特殊项目放在列表顶部。 我使用了一个TreeSet和一个特殊的Comparable类,它包含了他们正在使用的Locale来实现他们想要的东西。

然后我开始思考……正如你所做的那样…我通过从compareTo方法返回0来消除重复,而不是从equals实现返回true ,因为需要做的是正确地指示Set的重复(从一个Set的定义 )。

我不反对使用这种技术,但我使用的是什么可能被视为无证件的function ? 我可以安全地假设继续这样做会继续发挥作用吗?

看起来这在TreeSet JavaDoc (大胆的矿井)中有很好的记录:

请注意,如果要正确实现Set接口,则由set维护的排序(无论是否提供显式比较器) 必须与equals一致 。 (请参阅ComparableComparator以获得与equals一致的精确定义。)这是因为Set接口是根据equals操作定义的,但TreeSet实例使用compareTo (或compare)方法执行所有元素比较 ,因此从该集合的角度来看,通过这种方法被认为相等的元素是相等的。 集合的行为即使其排序与equals不一致也是明确定义的; 它只是不遵守Set接口的一般合同

下面是一个实现Comparable但与equals()不一致的唯一(?)JDK类的示例:

 Set decimals = new HashSet(); decimals.add(new BigDecimal("42")); decimals.add(new BigDecimal("42.0")); decimals.add(new BigDecimal("42.00")); System.out.println(decimals); 

decimals有三个值,因为42.042.00不等于equals() 。 但是如果用TreeSet替换HashSet ,结果集只包含1个项( 42 – 碰巧是第一个添加的项),因为当使用BigDecimal.compareTo()进行比较时,它们都被认为是相等的。

这表明当使用与equals()不一致的类型时, TreeSet处于“ 破坏 ”的状态。 它仍然正常工作,并且所有操作都是明确定义的 – 它只是不服从Set类的契约 – 如果两个类不equal() ,它们不被认为是重复的。

也可以看看

  • 比较与equals一致意味着什么? 如果我的class级不遵循这个原则,可能会发生什么?