-
Bug
-
Resolution: Duplicate
-
P4
-
None
-
11.0.4
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
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
- duplicates
-
JDK-8190545 (coll spec) SortedSet/Map should clarify use of comparison methods instead of equals()
-
- Open
-