containsAllofficial documentation(archive)仅表示“如果此列表包含指定集合的​​所有元素,则返回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));

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

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

最佳答案

List.containsAll 方法的行为与所记录的一样:如果给定集合的所有元素都属于此集合,则返回true,否则返回false。文档没有说元素的顺序或基数。containsAll的文档未明确说明如何确定元素是否属于Collection。但是contains的文档(隐式指定“contains”的语义)确实做到了:它使用equals。同样,没有提及基数。containsAll方法在 Collection 接口(interface)中声明,并在 List Set 接口(interface)中重新声明,但首先由 Collection 类在 AbstractCollection 层次结构中实现,如下所示:

public boolean containsAll(Collection<?> c) {
    for (Object e : c)
        if (!contains(e))
            return false;
    return true;
}
据我所知,该实现被Java Collections框架中实现 Collection 接口(interface)的大多数通用类继承,除了CopyOnWriteArrayList类和其他专用类(例如空列表以及检查和不可变的包装器等)。
因此,如果您看一下代码,就会发现它符合您引用的文档:

AbstractList.containsAll 方法的文档中,还有一个@implSpec标记,它表示以下内容:

关于可能的优化,它们全部传递给contains方法的不同实现,该方法也由 AbstractCollection 以一种幼稚的,类似蛮力的方式实现。但是,contains HashSet 中被覆盖以利用哈希,在 ArrayList 中也使用索引等被覆盖。

09-05 14:05