在Collection接口地址基数中包含containsAll()和retainAll()吗?

时间:2009-05-03 05:05:47

标签: java collections

在Java中,AbstractCollection类中的containsAll和retainAll明确声明基数不受尊重,因此换句话说,每边有多少个值实例并不重要。由于标准库中的所有Java集合都扩展了AbstractCollection,因此假设它们的工作方式相同。

但是,Collection接口中的这​​些方法的文档没有说什么。是否应该从AbstractCollection推断,或者是否故意未指定以允许定义不同的集合?

例如,apache-collections中的Bag明确声明它确实尊重基数,并声称它违反了Collection版本的合同(即使它实际上并非如此)。

那么,Collection中的这些操作的语义是什么,而不是AbstractCollection?

编辑:那些想知道我为什么会关心的人,这是因为作为我博士的一部分。我展示了开发人员不希望Apache中的一致性违规,但我试图理解为什么Collection接口如此模糊。

2 个答案:

答案 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)的多个可能结果都是合理的:

  1. 结果包含a和b
  2. 中至少有一个副本的每个元素中的一个
  3. 结果包含a中的每个元素(包括重复项),但不在b
  4. 中的元素除外
  5. 或者甚至,结果包含介于1和a中每个元素的a中的副本之间的某个位置,除了那些不在b中的副本。 我本来期望#1或#2,但根据合同,我认为三者中的任何一个都是合法的。
  6. AbstractCollection的javadoc确认它使用#2:

      

    这个实现迭代了这个   集合,检查每个元素   由迭代器依次返回   看看它是否包含在指定的中   采集。如果不是这样,   它已从此集合中删除   迭代器的删除方法

    虽然由于这不是我在阅读原始Collection接口的合同时,我不一定认为Collection的行为通常是这样的。

    也许您应该考虑在完成后向JavaDoc提交建议的更新。

    关于'为什么收集界面如此模糊' - 我严重怀疑它是故意做的 - 可能只是在编写API部分时没有给予应有的优先权。

答案 1 :(得分:0)

我不认为Collection以这种方式或其他方式定义它,但它只是成为遵循AbstractCollection行为的约定,例如google-collections:请参阅their Multiset documentation(Multiset就是它们叫一个袋子)