在Java中,AbstractCollection类中的containsAll和retainAll明确声明基数不受尊重,因此换句话说,每边有多少个值实例并不重要。由于标准库中的所有Java集合都扩展了AbstractCollection,因此假设它们的工作方式相同。
但是,Collection接口中的这些方法的文档没有说什么。是否应该从AbstractCollection推断,或者是否故意未指定以允许定义不同的集合?
例如,apache-collections中的Bag明确声明它确实尊重基数,并声称它违反了Collection版本的合同(即使它实际上并非如此)。
那么,Collection中的这些操作的语义是什么,而不是AbstractCollection?
编辑:那些想知道我为什么会关心的人,这是因为作为我博士的一部分。我展示了开发人员不希望Apache中的一致性违规,但我试图理解为什么Collection接口如此模糊。
答案 0 :(得分:2)
containsAll(在Collection中)的javadocs说:
返回:如果此集合为true 包含了中的所有元素 指定的集合
和retainAll(在Collection中):
仅保留此中的元素 包含在中的集合 指定集合(可选 操作)。换句话说,删除 从这个集合的所有 未包含在内的元素 指定的集合。
我读到containsAll的契约意味着调用a.containsAll(b)将返回true,当且仅当为b中的每个元素调用a.contains(bElem)时bElem将返回true。我也想把它暗示a.containsAll(someEmptyCollection)也会返回true。正如您所说,AbstractCollection的javadoc更明确地说明了这一点:
这个实现迭代了 指定的集合,检查每个 迭代器返回的元素 转过来看看它是否包含在内 采集。如果所有元素都是如此 包含true,否则返回true 假的。
我同意Collection for Contain的联系方式应该更明确,以避免任何混淆的可能性。 (而且,为了确认对Collection的理解,不应该读取AbstractCollection的javadoc)
在调用retainAll之后,我不会对重复元素的数量做出假设。 Collection中所述的合同(通过我的阅读)并不意味着如何处理任何一个集合中的重复。基于我对retainAll的收集,a.retainAll(b)的多个可能结果都是合理的:
AbstractCollection的javadoc确认它使用#2:
这个实现迭代了这个 集合,检查每个元素 由迭代器依次返回 看看它是否包含在指定的中 采集。如果不是这样, 它已从此集合中删除 迭代器的删除方法
虽然由于这不是我在阅读原始Collection接口的合同时,我不一定认为Collection的行为通常是这样的。
也许您应该考虑在完成后向JavaDoc提交建议的更新。
关于'为什么收集界面如此模糊' - 我严重怀疑它是故意做的 - 可能只是在编写API部分时没有给予应有的优先权。
答案 1 :(得分:0)
我不认为Collection以这种方式或其他方式定义它,但它只是成为遵循AbstractCollection行为的约定,例如google-collections:请参阅their Multiset documentation(Multiset就是它们叫一个袋子)