我有下面的代码,它使用基于字符串长度的比较器创建一个 TreeSet。
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);
}
}
令我惊讶的是上面的输出是
[aa]
虽然我期望
[aa, bb]
or
[bb, aa]
“bb”部分消失了,这似乎违反了 SortedSet 契约。比较器应该只对元素进行排序,而不确定它们的唯一性,这通常由 equals 确定。
另一方面,如果我增强比较器以始终为如下所示的不相等项返回非零,只有这样我才能得到正确的结果。
SortedSet<String> sortedSet = new TreeSet<>(Comparator.comparing(String::length).reversed().thenComparing(String::toString));
sortedSet.addAll(Arrays.asList("aa", "bb", "aa"));
System.out.println(sortedSet);
现在的输出是[aa, bb]
正如我所期望的。
以上是 TreeSet 实现中的错误吗?
我的环境如下:
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
以下是相关帖子以及有关如何在未来版本的 Java 中解决该问题的建议:https://yesday.github.io/blog/2018/java-gotchas-sorted-set-ignores-the-equals-method.html