这是TreeSet< E>的实现中的不一致,接近bug.当传递给removeAll的集合中的项目数大于或等于集合中的项目数时,代码将忽略自定义比较器.
不一致是由一个小优化引起的:如果你看一下removeAll的implementation,它继承自AbstractSet,那么优化如下:
public boolean removeAll(Collection> c) {
boolean modified = false;
if (size() > c.size()) {
for (Iterator> i = c.iterator(); i.hasNext(); )
modified |= remove(i.next());
} else {
for (Iterator> i = iterator(); i.hasNext(); ) {
if (c.contains(i.next())) {
i.remove();
modified = true;
}
}
}
return modified;
}
你可以看到,当c的项目少于这个集合(顶部分支)时,行为是不同的,当它具有更多或更多项目(底部分支)时.
Top branch使用与此set相关联的比较器,而bottom branch使用equals进行比较c.contains(i.next()) – 所有这些都在同一个方法中!
您可以通过向原始树集添加一些额外元素来演示此行为:
s.addAll(Arrays.asList("x", "z", "a", "b"));
现在两个测试用例的输出变得相同,因为remove(i.next())使用了集合的比较器.