具有重复项的“containsAll”行为

Fab*_*ing 7 java collections list duplicates

官方文档( archive )containsAll只说“如果此列表包含指定集合的​​所有元素,则返回 true。”。但是,我只是测试了这个:

List<Integer> list1 = new ArrayList<>();
list1.add(1);
list1.add(2);
list1.add(1);
List<Integer> list2 = new ArrayList<>();
list2.add(2);
list2.add(1);
list2.add(2);
System.out.println(list1.containsAll(list2));
Run Code Online (Sandbox Code Playgroud)

结果是true,即使list1不包含第二个2

那么官方的、完全定义的行为是containsAll什么?它是否好像从两个列表中删除了所有重复项?我记得在某处读到它可能会导致重复问题,但我不知道确切的情况。

Fed*_*ner 5

List.containsAll方法的行为与记录的一样:true如果给定集合的所有元素都属于该集合,则返回,false否则返回。文档没有说明元素的顺序或基数。

的文档containsAll没有明确说明它如何确定元素是否属于Collection. 但是contains(隐式指定“包含”的语义)的文档确实:它使用equals. 同样,没有提到基数。

containsAll方法在Collection接口中声明,在ListSet接口中重新声明,但首先CollectionAbstractCollection类在层次结构中实现,如下所示:

public boolean containsAll(Collection<?> c) {
    for (Object e : c)
        if (!contains(e))
            return false;
    return true;
}
Run Code Online (Sandbox Code Playgroud)

据我所知,CollectionJava Collections 框架中实现接口的大多数常见类都继承了这个实现,除了CopyOnWriteArrayList类和其他专门的类,如空列表和检查和不可变包装器等。

因此,如果您查看代码,您会发现它符合您引用的文档:

返回true此列表是否包含指定集合的​​所有元素。

在该AbstractList.containsAll方法的文档中,还有一个@implSpec标签,内容如下:

@implSpec

此实现迭代指定的集合,依次检查迭代器返回的每个元素以查看它是否包含在此集合中。如果所有元素都如此包含,true则返回,否则返回false

关于可能的优化,它们都被传递到该contains方法的不同实现中,这些实现也AbstractCollection以一种天真的、类似蛮力的方式实现。但是,contains在 ie 中被覆盖HashSet以利用散列,也在 中ArrayList使用索引等。