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

TreeSet::add method doesn't not use Objects.equals to check collision

XMLWordPrintable

      A DESCRIPTION OF THE PROBLEM :
      The official documentation for TreeSet:add methods says that "adds the specified element e to this set if the set contains no element e2 such that Objects.equals(e, e2). If this set already contains the element, the call leaves the set unchanged and returns false" but in practice looks like is using the e.compareTo(e2) method for checking the existence of the element.
      https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/TreeSet.html#add(E)

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Create 2 objects for which Objects.equals(e, e2) returns true but e.compareTo(e2) returns false.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      based on the available documentation the second element should not be added to the set.
      ACTUAL -
      What is happening is that both elements will be added to the set because e.compareTo(e2) method returns false (and Objects.equals(e, e2) is just ignored)

      ---------- BEGIN SOURCE ----------
      import java.util.Objects;
      import java.util.TreeSet;

      public class BugReport {
          public static void main(String[] args) {

              TreeSet<MySeason> seasons = new TreeSet<>();

              MySeason s1 = new MySeason(2019, "Summer", 72.0);
              MySeason s2 = new MySeason(2019, "Winter", 87.0);

              System.out.println("s1 was added : " + seasons.add(s1));
              System.out.println("s2 was added : " + seasons.add(s2));

              System.out.println("Objects.equals(s1, s2): " + Objects.equals(s1, s2));
              System.out.println("s1.compareTo(s2): " + (s1.compareTo(s2) == 0));

              System.out.println("seasons = " + seasons);
          }
      }

      class MySeason implements Comparable<MySeason> {
          private final int year;
          private final String name;
          private final double humidity;

          public MySeason(int year, String name, double humidity) {
              this.year = year;
              this.name = name;
              this.humidity = humidity;
          }

          @Override
          public boolean equals(Object o) {
              if (this == o) return true;
              if (o == null || getClass() != o.getClass()) return false;
              MySeason season = (MySeason) o;
              return year == season.year;
          }

          @Override
          public int compareTo(MySeason o) {
              int result = Integer.compare(year, o.year);

              return result != 0 ? result : name.compareTo(o.name);
          }

          @Override
          public String toString() {
              return name + "(" + year + ", " + humidity + "%)";
          }
      }
      ---------- END SOURCE ----------

      FREQUENCY : always


            psonal Pallavi Sonal (Inactive)
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: