在处理树集时,我发现了非常奇怪的行为。
根据我的理解,以下程序应该打印两行相同的行:
public class TestSet {
static void test(String... args) {
Set<String> s = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
s.addAll(Arrays.asList("a", "b"));
s.removeAll(Arrays.asList(args));
System.out.println(s);
}
public static void main(String[] args) {
test("A");
test("A", "C");
}
}
但奇怪的是它打印:
[b]
[a, b]
我无法理解 - 为什么树集会这样?
发生这种情况是因为 SortedSet 的 Comparator 用于排序,但 removeAll 依赖于equals
每个元素的方法。来自排序集文档 http://docs.oracle.com/javase/8/docs/api/java/util/SortedSet.html:
请注意,排序集维护的顺序(无论是否提供显式比较器)必须是与等于一致如果排序集要正确实现Set
界面。 (参见Comparable
接口或Comparator
接口的精确定义与平等一致。)这是因为Set
接口是根据以下定义的equals
操作,但排序集使用其执行所有元素比较compareTo
(or compare
) 方法,因此从排序集的角度来看,被该方法视为相等的两个元素是相等的。有序集的行为is定义良好,即使其顺序与 equals 不一致;它只是没有遵守总合同Set
界面。
“与等于一致”的解释定义在类似的文档 http://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html:
类的自然排序C
据说是与等于一致当且仅当e1.compareTo(e2) == 0
具有相同的布尔值e1.equals(e2)
对于每一个e1
and e2
班级的C
。注意null
不是任何类的实例,并且e.compareTo(null)
应该抛出一个NullPointerException
虽然e.equals(null)
回报false
.
强烈建议(尽管不要求)自然排序与 equals 保持一致。之所以如此,是因为没有显式比较器的排序集(和排序映射)在与自然顺序与 equals 不一致的元素(或键)一起使用时表现得“奇怪”。特别是,这样的排序集(或排序映射)违反了集合(或映射)的一般契约,该契约是根据equals
method.
总之,集合的比较器的行为与元素的不同equals
方法,导致异常(尽管可以预测)的行为。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)