Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8278269

ConcurrentSkipListSet::add works not based on equality

XMLWordPrintable

      ADDITIONAL SYSTEM INFORMATION :
      Debian 5.14.9-2 (2021-10-03) x86_64 GNU/Linux
      openjdk version "17.0.1" 2021-10-19
      OpenJDK Runtime Environment (build 17.0.1+12-Debian-1)
      OpenJDK 64-Bit Server VM (build 17.0.1+12-Debian-1, mixed mode, sharing)


      A DESCRIPTION OF THE PROBLEM :

      A set is a collection of distinct objects.
      Objects are different if a.equals(b) == false.

      import java.util.concurrent.ConcurrentSkipListSet behaves differently since the equality of objects is determined by the compareTo method of contained objects.

      The following snippet shows this.
      For the sake of the argument the implementation of compareTo always returns 0, which makes them even but not equal.

      import java.util.HashSet;
      import java.util.concurrent.ConcurrentSkipListSet;

      public class NewClass {

      static class E implements Comparable<E> {

      @Override
      public int compareTo(E t) {
      return 0;
      }

      }

      public static void main(String[] args) {

      var set = new HashSet<E>();
      var conc_set = new ConcurrentSkipListSet<E>();

      for (var i = 0; i < 5; i++) {
      set.add(new E());
      conc_set.add(new E());
      }

      System.out.println("set size: " + set.size());
      System.out.println("concurrent set size: " + conc_set.size());

      /**
      * set size: 5
      * concurrent set size: 1
      */
      }

      }

      Imho the sets should behave similarly.
      The documentation of ConcurrentSkipListSet::add also describes adding wrt equality.

        /**
           * Adds the specified element to this set if it is not already present.
           * More formally, adds the specified element <tt>e</tt> to this set if
           * the set contains no element <tt>e2</tt> such that <tt>e.equals(e2)</tt>.
           * If this set already contains the element, the call leaves the set
           * unchanged and returns <tt>false</tt>.
           */


      Maybe I misinterpret sth. here but at least the documentation should note that equality is not used in this kind of set.


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      See code example.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Set and ConcurrentSkipListSet should behave in similar ways.
      ACTUAL -
      ConcurrentSkipListSet adds elements only if compareTo != 0 no matter if equals is false.

      ---------- BEGIN SOURCE ----------
      import java.util.HashSet;
      import java.util.concurrent.ConcurrentSkipListSet;

      public class NewClass {

      static class E implements Comparable<E> {

      @Override
      public int compareTo(E t) {
      return 0;
      }

      }

      public static void main(String[] args) {

      var set = new HashSet<E>();
      var conc_set = new ConcurrentSkipListSet<E>();

      for (var i = 0; i < 5; i++) {
      set.add(new E());
      conc_set.add(new E());
      }

      System.out.println("set size: " + set.size());
      System.out.println("concurrent set size: " + conc_set.size());

      /**
      * set size: 5
      * concurrent set size: 1
      */
      }

      }
      ---------- END SOURCE ----------

      FREQUENCY : always


            smarks Stuart Marks
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: