Java ConcurrentSkipListSet与文档不一致

时间:2014-03-15 04:25:46

标签: java groovy java.util.concurrent

问题: 包含和添加ConcurrentSkipListSet(csls)的文档声明如下:

public boolean add(E e) 如果指定的元素尚不存在,则将其添加到此集合中。更正式地,如果集合不包含e.equals(e2)的元素e2,则将指定的元素e添加到该集合。如果此set已包含该元素,则调用将保持set不变并返回false。

public boolean contains(Object o) 如果此set包含指定的元素,则返回true。更正式地说,当且仅当此集合包含o.equals(e)的元素e时才返回true。

但我没有看到这种行为。下面的代码(单元测试)揭示了这种差异。

@Test
public void testComparison() throws Exception {
    ObjectKey key = new ObjectKey("a", "b")
    MetricTimeDataContext entry1 = new MetricTimeDataContext(1l, "Count", 10, 0, key)
    MetricTimeDataContext entry2 = new MetricTimeDataContext(1l, "Count", 10, null, key)
    Assert.assertEquals(1, entry1 <=> entry2) // the compare shows entry1 > entry2
    Assert.assertNotEquals(entry1, entry2)    // entry != entry2
    Assert.assertEquals(Boolean.FALSE, entry2.equals(entry1))  // EDIT: Added this since documentation states it is performing this test. this passes..
    Assert.assertNotEquals(entry1.hashCode(), entry2.hashCode())  // hashcodes are diff

    // this block shows correct functionality of ConcurrentHashMap
    def final Map<MetricTimeDataContext, Boolean> store = new ConcurrentHashMap<>()
    store.put(entry1, Boolean.TRUE)
    Assert.assertFalse(store.containsKey(entry2)) // correct! since entry1 != entry2
    store.put(entry2, Boolean.TRUE)
    Assert.assertEquals(2, store.size())  // correct! 2 items added.

    // this block shows INcorrect functionality of ConcurrentSkipListSet
    def final Set<MetricTimeDataContext> dataStore = new ConcurrentSkipListSet<>()
    Assert.assertTrue(dataStore.add(entry1))
    Assert.assertFalse(dataStore.contains(entry2)) // <--- this line fails unit test. why ???
    Assert.assertTrue(dataStore.add(entry2))  // <-- this line also fails if above line is absent

}

我错过了一些明显的东西吗?上面的条目(entry1,entry2)显然不相等,但我不能将它们都添加到csls中。是什么赋予了?

我需要使用Concurrent数据结构,因为此代码将用于分布式env(akka)。此外,MetricTimeDataContext实现了与上面的单元测试中所示的相似,并且具有适当的equals和hashcode实现。

感谢。

更新:[已解决] 所以感谢@mbs和@JasonC的推动,我在最顶层再增加了两个测试:

Assert.assertEquals(Boolean.FALSE,entry2.equals(entry1))//这传递(相等很好) Assert.assertEquals(-1,entry2&lt; =&gt; entry1)//这返回0而不是-1(comp被破坏)

所以我的比较算法不正确。

再次感谢。

Java:

java version "1.7.0_21"
Java(TM) SE Runtime Environment (build 1.7.0_21-b11)
Java HotSpot(TM) 64-Bit Server VM (build 23.21-b01, mixed mode)

Groovy的:

[INFO] \- org.codehaus.groovy:groovy-all:jar:2.1.5:compile

平台:

Linux ariel 3.5.0-43-generic #66~precise1-Ubuntu SMP Thu Oct 24 14:52:23 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

2 个答案:

答案 0 :(得分:1)

很可能你的等号很好(因为ConcurrentHashMap很好)但是compareTo不匹配(因为ConcurrentSkipListMap是个问题)。我会在你的测试中检查compareTo和equals对于你正在使用的对象是否一致。

答案 1 :(得分:0)

我在发布后的几分钟内将此更新添加到我的原始帖子,因为SO不允许您回答8小时的问题。

所以我在最顶层再添加了两个测试:

Assert.assertEquals(-1, entry2 <=> entry1) // this returns 0 instead of -1
Assert.assertEquals(Boolean.FALSE, entry2.equals(entry1))

所以我的比较算法不正确。 @JasonC在发布此内容后约15分钟就打了这个。

此外,文档具有误导性,因为它明确指出添加取决于它不相等的等于。添加取决于compareTo,在我的情况下,entry2.compareTo(entry1)返回0而不是-1。

当然,最佳做法是使equals与compareTo逻辑匹配。

感谢所有回应。