为什么Java集合框架中没有直接实现Bag?

24

我无法理解为什么JCF(Java Collection Framework)没有一个Bag实现(允许重复并且不维护顺序)。 比起JCF当前的集合实现,Bag性能会更好。

  • 我知道如何在Java中实现Bag
  • 我知道Bag在Apache commons中可用。
  • 我知道还有其他可用作Bag的实现,但与Bag相比,这些实现需要做更多的工作。

为什么Java Collections框架没有提供像这样的直接实现呢?


这可能值得一看:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6567419 - Ajay George
4个回答

15
发布我的评论作为答案,因为它最好地回答了这个问题。
这里提交的错误报告中:
引用: 维护Collection框架的人员中并没有太多的热情来设计和实现这些接口/类。我个人无法回忆起自己曾经需要过这样一个接口/类。更有可能的是,在经过在现实世界中证明其价值后,从JDK之外开发的受欢迎的包会被导入到JDK中。
如今,对于支持Bags的需求是合理的。 Guava对此提供了支持。还有GS-Collections

5
当我需要生成集合的哈希值时,我确实需要使用一个"Bag",不考虑排序但考虑重复项。List.hashcode()会考虑元素的顺序。Set.hashset()可以正确地忽略顺序,但也会忽略重复的元素。在这种情况下,唯一正确的hashcode()实现可能是Bag实现。这是一个典型的JSON签名问题。 - DLopes

3

目前,Bag违反了集合合同。许多方法与当前的集合规则冲突。

"Bag是一个计算对象在集合中出现次数的集合。假设您有一个包含{a,a,b,c}的Bag。调用getCount(Object)并传入a将返回2,而调用uniqueSet()将返回{a,b,c}

请注意,该接口违反了Collection合同。这些方法中许多指定的行为与Collection指定的行为不同。不符合要求的方法在其摘要行中用“(Violation)”明确标记。未来版本的此类将指定与Collection相同的行为,不幸的是,这将破坏与此版本的向后兼容性。"

 boolean add(java.lang.Object o)
      (Violation) Add the given object to the bag and keep a count.

 boolean removeAll(java.util.Collection c)
      (Violation) Remove all elements represented in the given collection, respecting cardinality.

请参见以下链接以获取更多信息:这里

1
请在链接中包含文本。 - deW1
3
什么是收藏品合约? - Junchen Liu
你引用的文档部分并不违规。 - Jimmy T.
@JimmyT。这确实违反了规则,因为Bag会保持计数。而Collection不会保持计数,因为它将数据插入到结构中。Bag本身的文档说明它违反了Collection的规则。'add'和'removeAll'方法也是如此。 - Rahul
2
违规只在于返回值。计数仅是重复项的不同表示方式。这本身并不违反接口。 - Jimmy T.

0
JDK试图为您提供常见数据结构的实现,并允许您实现任何东西,如果常见结构无法满足您的目的。他们可能认为这不是常见的数据结构。从实用性角度来看,他们不可能实现所有存在的数据结构或满足每个人的要求。您认为常见的可能并不是大多数人认为的常见。

1
Bag在集合领域非常常见!我经常看到人们使用其他集合实现而不是Bag,只是因为JCF中没有任何直接的Bag实现,所以他们必须支付其他集合的一些额外开销。我相信Bag是最常用的集合。 - Morteza Adi
“Bag在集合领域非常常见”,这是您的经验。在我的职业生涯中,我只使用过一次Bag/Multiset。我猜这取决于您正在处理什么。 - Adisesha
Ajay George 提供的问题链接可以回答你的问题。 - Adisesha

0
可以直接使用一个Map<Object, Long> bag
add方法看起来会像这样。
bag.merge(obj, 1, Integer::sum);

删除类似的内容
bag.merge(obj, -1, (a, b) -> a > 1 ? a + b : 0);

这至少是Apache common-collections4 HashBag的基础。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接