【发布时间】:2013-08-08 10:04:30
【问题描述】:
我发现AbstractSets 的removeAll 方法在处理单个Comparators 时的这种奇怪行为。
根据比较集合的大小,使用不同的比较器。
它实际上记录在 API 中,但我仍然看不到它背后的原因。
代码如下:
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.
*/
}
}
【问题讨论】:
-
始终将相关代码等放在问题本身中,不要只是链接。
-
您还应该在问题中包含一个问题。
-
这个问题的读者可能也对这个Java错误报告感兴趣,JDK-4730113 : TreeSet removeAll(), retainAll() don't use comparator; addAll() does。