I have the below code which creates a TreeSet using a comparator based on string length.
public class TreeSetComparator {
public static void main(String[] args) {
SortedSet<String> sortedSet = new TreeSet<>(Comparator.comparing(String::length));
sortedSet.addAll(Arrays.asList("aa", "bb", "aa"));
System.out.println(sortedSet);
}
}
To my surprise the output of the above is
[aa]
While I would expect
[aa, bb]
or
[bb, aa]
The "bb" part disappears, which seems to be contrary to the SortedSet contract. The comparator is supposed to only sort the elements and not determine their uniqueness, which is normally determined by equals.
On the other hand, if I enhance the comparator to always return non-zero for unequal items like below, only then do I get the correct results.
SortedSet<String> sortedSet = new TreeSet<>(Comparator.comparing(String::length).reversed().thenComparing(String::toString));
sortedSet.addAll(Arrays.asList("aa", "bb", "aa"));
System.out.println(sortedSet);
The output now is [aa, bb]
as I would expect.
Is the above a bug in the TreeSet implementation?
My environment is as follows:
mvn --version 21:40:22
Apache Maven 3.5.4 (1edded0938998edf8bf061f1ceb3cfdeccf443fe; 2018-06-17T19:33:14+01:00)
Maven home: /home/aaaa/.sdkman/candidates/maven/current
Java version: 10.0.2, vendor: Oracle Corporation, runtime: /usr/lib/jvm/java-10-jdk
Default locale: en_GB, platform encoding: UTF-8
OS name: "linux", version: "4.14.60-1-manjaro", arch: "amd64", family: "unix"
UPDATE
Here is a related post along with suggestions on how to fix the issue in a future version of Java: https://yesday.github.io/blog/2018/java-gotchas-sorted-set-ignores-the-equals-method.html