【问题标题】:Java: What happens when Comparator (a, b) == 0 for ConcurrentSkipListSet?Java:当 ConcurrentSkipListSet 的 Comparator (a, b) == 0 时会发生什么?
【发布时间】:2011-12-15 19:58:19
【问题描述】:

我正在使用java.util.concurrent.ConcurrentSkipListSet。我定义了一个类People,它的对象保存在ConcurrentSkipListSet<People> 中,一个Comparator<People> 比较AgePeople,而ConcurrentSkipListSet<People> 对象是通过这个Comparator<People> 构造的。

如果我有两个 People 对象具有相同的 Age,例如a.Age.equals(b.Age),会发生什么? ab 都在 ConcurrentSkipListSet?还是只有一个?

要求这样的Comparator必须与equals一致,但就我而言,a.Age.equals(b.Age)绝对不代表a.equals(b) 。我只想按AgePeople 对象进行排序。

现在我的比较器实现如下:

    class ComparatorHSD implements Comparator<People> {  
        public int compare(People s0, People s1) {  
        int rv = 0;  
        if (s0.Age > s1.Age) {
            rv = 1;
        } else if (s0.Age < s1.Age) rv = -1;
        return rv;
    }  

如果我不定义rv = 0,程序似乎卡在某个地方并且不会终止。所以我已经定义了吗?为什么?

【问题讨论】:

  • @gurung 为什么将代码示例用斜体表示?为什么是一些而不是全部?
  • @toto2 大减1。比较时不要走减法的捷径。 stackoverflow.com/questions/2728793/…
  • 其实并没有像@glowcoder 想的那样工作:ConcurrentSkipListSet 是基于完全有序的Set,所以no 可以添加重复元素。
  • 是和不是。这取决于您所说的重复是什么意思。关键是在一个集合中,不会有两个非空元素ab 使得set.contains(a) &amp;&amp; set.contains(b) &amp;&amp; a.equals(b) 为真。这可能取决于也可能不取决于您的ComparatorcompareTo 方法是否与equals 一致。在您的情况下,由于它在文档中这么说,它要求它们是平等的。
  • 简单地说,你不想用这个数据结构来排序。使用ArrayList 或其他东西。 :)

标签: java sorting concurrency comparator


【解决方案1】:

与equals一致仅仅意味着a.equals(b)(不是==...)意味着a.compareTo(b) == 0。就是这样。

就排序而言,这意味着您在相等值的范围内有一个未定义的顺序。

我还应该注意,根据java.util.Comparator 的javadoc,

一般是这样,但不严格要求 (compare(x, y)==0) == (x.equals(y))。

尽管通常可以假设是这种情况,除非另有说明。 (您在该假设下承担多少业务风险取决于您。)

【讨论】:

  • 所以,关于我的例子,ab 都在 ConcurrentSkipListSet&lt;People&gt; 中,但是它们的 order 是未定义的。对吗?
  • 如果您的 a,b,c,d,e 年龄依次为 20,20,19,21,19,那么比较器有 4 种可能的结果:c,e,a,b,d e,c,a,b,d c,e,b,a,d e,c,b,a,d - ce 可能在另一个之前或之后,但它们将在所有其他之前。 ab 将介于 19 和 21 之间,而 21 将在末尾。有意义吗?
  • 一个后续问题 - 我该怎么做才能获得像 a,c,d 这样的集合...基本上我不希望我的集合中有重复的元素。
  • @crucifix94 你不能在集合中得到重复的元素。这就是你使用集合的原因。如果你确实有重复的元素,要么你没有使用集合,要么你的集合中有一个错误,或者你的 equals(和/或 hashCode)实现中有一个错误。
【解决方案2】:

我认为这是一个有争议的问题,因为您不能将 Comparator&lt;Age&gt;ConcurrentSkipListSet&lt;People&gt; 一起使用。查看javadoc,它表明Age 必须是People 的超类型,我想它不是。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-02
    • 1970-01-01
    • 2016-01-17
    • 1970-01-01
    • 2017-06-11
    • 2021-02-01
    • 1970-01-01
    相关资源
    最近更新 更多