Java ConcurrentSkipListSet несовместим с документацией

1

Проблема: в документации для contains и add для ConcurrentSkipListSet (csls) указано следующее:

public boolean add (E e) Добавляет указанный элемент к этому набору, если он еще не присутствует. Более формально добавляет заданный элемент e к этому набору, если в наборе нет элемента e2 такого, что e.equals(e2). Если этот набор уже содержит элемент, вызов оставляет его неизменным и возвращает false.

public boolean contains (Object o) Возвращает true, если этот набор содержит указанный элемент. Более формально возвращает true тогда и только тогда, когда этот набор содержит элемент e такой, что o.equals(e).

Но я не вижу такого поведения. Приведенный ниже код (единичный тест) раскрывает несоответствие.

@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. что дает?

Мне нужно использовать параллельную структуру данных, так как этот код будет использоваться в распределенном env (akka). Также MetricTimeDataContext реализует сравнимые, как показано в приведенном выше модульном тесте, и имеет соответствующие значения equals и hashcode.

Благодарю.

UPDATE: [SOLVED] Итак, благодаря подталкиванию @mbs и @JasonC я добавил еще 2 теста на самом верху:

Assert.assertEquals(Boolean.FALSE, entry2.equals(entry1))//это проходит (равенство в порядке) Assert.assertEquals(-1, entry2 <=> entry1)//это возвращает 0 вместо -1 (comp сломан)

Поэтому мой алгоритм сравнения неверен. ,

Еще раз спасибо.

Ява:

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
Теги:
groovy
java.util.concurrent

2 ответа

1

Скорее всего, ваши равноценны (поскольку ConcurrentHashMap в порядке), но compareTo не соответствует (поскольку проблема ConcurrentSkipListMap является проблемой). Я бы проверил в вашем тесте, что compareTo и equals соответствуют объектам, которые вы используете.

0

Я добавил это обновление в свое первоначальное сообщение после нескольких минут после публикации, так как SO не позволяет вам отвечать на собственный вопрос в течение 8 часов.

Поэтому я добавил еще 2 теста на самом верху:

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.

Разумеется, лучше всего иметь равные с вашей логикой compareTo.

Так спасибо всем, кто ответил.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню