为了账号安全,请及时绑定邮箱和手机立即绑定

ConcurrentSkipListSet中添加的重复项

ConcurrentSkipListSet中添加的重复项

长风秋雁 2019-04-18 18:15:10
我试图在ConcurrentSkipListSet中维护插入顺序。要添加的项是具有value(String)和index(int)属性的自定义类类型。它实现了Comparable接口。该集的行为非常不一致,有时会添加重复项。如果项目具有相同的值,则视为重复。// This is the Item class being added in the set.final class Item implements Comparable<Item> {         private String value;         private int index;         Item(String val, int idx) {             this.value = val;             this.index = idx;         }         @Override         public int compareTo(Item o) {             // returns zero when values are equal indicating it's a duplicate item.             return this.value.equals(o.value) ? 0 : this.index - o.index;         }         @Override         public String toString() {             return this.value;         }     }// Below is the main class.public class Test {     ConcurrentSkipListSet<Item> set;     AtomicInteger index;     public Test() {         set = new ConcurrentSkipListSet<>();         index = new AtomicInteger(0);     }     public static void main(String[] args) {         for (int i = 1; i <= 10; i++) {             Test test = new Test();             test.addItems();             test.assertItems();         }     }//trying to test it for 10 times. It always fails for once or twice.     private void assertItems() {         Iterator<Item> iterator = set.iterator();         String[] values = {"yyyy", "bbbb", "aaaa"};         for (String value : values) {             if (!value.equals(iterator.next().toString())) {                 System.out.println("failed for :" + set);                 return;             }         }         System.out.println("passed for :" + set);     }预期:通过:[yyyy,bbbb,aaaa]实际:失败:[yyyy,bbbb,yyyy,aaaa]但如前所述,结果非常不一致。大多数时候,它都过去了。请告诉我这可能是什么原因。'compareTo()'方法是错误的吗?如果是这样,它应该总是失败。理想情况下,我们也应该覆盖'equals()'方法。但是从排序集的角度来看并不重要。感谢您的帮助。
查看完整描述

3 回答

?
慕妹3146593

TA贡献1820条经验 获得超9个赞

在你的compareTo实现中,你以非法的方式混合了两个不同的属性。因此,您违反了Comparable接口的合同。

在比较中,只有在值不相等时才查看索引。这样,您就无法为商品定义整体自然顺序。根据首先进行的比较,排序列表的结果将是随机的。

    @Override
    public int compareTo(Item o) {
        int vCompare = this.value.compareTo(o.value);
        if (vCompare == 0) {
            return  this.index - o.index;
        }
        return vCompare;
    }

此实现将首先按值进行比较,然后按索引进行比较。它遵循Comparable合同,实际上定义了Items的自然顺序,并且与Set实现一起工作正常。

警告:此示例实现将破坏测试。测试用于显示代码的行为符合预期。但在这种情况下,预期的行为是实际问题。

  • 它与可比较合同不相容。

  • 您不能按数字索引对列表进行排序,并希望按字母顺序查找值才能成功。但这正是这里所尝试的。按索引排序但找到重复的名称。它没有这种方式。


查看完整回答
反对 回复 2019-05-15
?
暮色呼如

TA贡献1853条经验 获得超9个赞

我不详细了解ConcurrentSkipListSet的实现,但看起来你需要覆盖类的equals方法来指定限定两个对象相等的条件。


查看完整回答
反对 回复 2019-05-15
  • 3 回答
  • 0 关注
  • 1789 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号