containsAll
的official 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
中也使用索引等被覆盖。