ConcurrentSkipListSet中添加的重复项

我试图在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()'方法。但是从排序集的角度来看并不重要。

感谢您的帮助。


长风秋雁
浏览 1790回答 3
3回答

慕妹3146593

在你的compareTo实现中,你以非法的方式混合了两个不同的属性。因此,您违反了Comparable接口的合同。在比较中,只有在值不相等时才查看索引。这样,您就无法为商品定义整体自然顺序。根据首先进行的比较,排序列表的结果将是随机的。&nbsp;&nbsp;&nbsp;&nbsp;@Override &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;int&nbsp;compareTo(Item&nbsp;o)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;vCompare&nbsp;=&nbsp;this.value.compareTo(o.value); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(vCompare&nbsp;==&nbsp;0)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;&nbsp;this.index&nbsp;-&nbsp;o.index; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;vCompare; &nbsp;&nbsp;&nbsp;&nbsp;}此实现将首先按值进行比较,然后按索引进行比较。它遵循Comparable合同,实际上定义了Items的自然顺序,并且与Set实现一起工作正常。警告:此示例实现将破坏测试。测试用于显示代码的行为符合预期。但在这种情况下,预期的行为是实际问题。它与可比较合同不相容。您不能按数字索引对列表进行排序,并希望按字母顺序查找值才能成功。但这正是这里所尝试的。按索引排序但找到重复的名称。它没有这种方式。

暮色呼如

我不详细了解ConcurrentSkipListSet的实现,但看起来你需要覆盖类的equals方法来指定限定两个对象相等的条件。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java