集合中 removeAll 方法的不直观行为 [英] Unintuitive behavior of removeAll method in sets
问题描述
我在使用单个 Comparator
时发现了 AbstractSets
的 removeAll
方法的这种奇怪行为.
I discovered this weird behavior of the removeAll
method of AbstractSets
when working with individual Comparators
.
根据比较集合的大小,使用不同的比较器.
Depending on the size of the compared collections a different comparator is used.
它实际上记录在 API 中,但我仍然看不到其背后的原因.
It is actually documented in the API but I still cannot see the reason behind it.
代码如下:
import java.util.Comparator;
import java.util.Set;
import java.util.Stack;
import java.util.TreeSet;
public class Test {
public static void main(String[] args) {
// Any comparator. For this example, the length of a string is compared
Set<String> set = new TreeSet<String>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
});
set.add("a");
set.add("aa");
set.add("aaa");
set.add("aaaa");
System.out.println(set); // output: [a, aa, aaa, aaaa]
Stack<String> stack = new Stack<String>();
stack.push("b");
stack.push("bb");
stack.push("bbb");
stack.push("bbbb");
set.removeAll(stack); // NO ITEMS ARE REMOVED from the set
System.out.println(set); // output: [a, aa, aaa, aaaa]
// Now let's see what happens if I remove an object from the stack
stack.pop();
set.removeAll(stack); // ALL ITEMS from the stack are removed from the
// set
System.out.println(set); // output: [aaaa]
/* Reason for this strange behaviour: Depending on the size of the
* passed Collection, TreeSet uses either the remove() function of
* itself, or from the Collection object that was passed. While the
* remove() method of the TreeSet uses the comparator to determine
* equality, the remove() method of the passed usually determines
* equality by calling equals() on its objects.
*/
}
}
推荐答案
您基本上创建了未定义的行为,因为您的集合具有不同的相等标准.以任何方式组合集合只有在它们具有相同的情况下才能起作用.您基本上违反了 A.equals(B)
必须产生与 B.equals(A)
相同的结果的约定.
You have basically created undefined behavior since your sets have different criteria of equality. Combining collections in any way can only work if they have the same. You are basically violating the contract that A.equals(B)
must yield the same result as B.equals(A)
.
可比:强烈推荐(虽然不是必需的)自然顺序与 equals 一致.之所以如此,是因为没有显式比较器的排序集(和排序映射)在与自然顺序与 equals 不一致的元素(或键)一起使用时表现得奇怪".特别是,这样的排序集合(或排序映射)违反了集合(或映射)的一般约定,后者是根据 equals 方法定义的.
Comparable: It is strongly recommended (though not required) that natural orderings be consistent with equals. This is so because sorted sets (and sorted maps) without explicit comparators behave "strangely" when they are used with elements (or keys) whose natural ordering is inconsistent with equals. In particular, such a sorted set (or sorted map) violates the general contract for set (or map), which is defined in terms of the equals method.
这篇关于集合中 removeAll 方法的不直观行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!