类似于 Java 的 EnumSet 的结构,可以容纳重复的元素

Structure like Java's EnumSet that can hold repeated elements

我需要一些结构来存储 N 个枚举,其中一些是重复的。并能够轻松提取它们。到目前为止,我已经尝试像这样使用 EnumSet。

cards = EnumSet.of(
                BEST_OF_THREE,
                BEST_OF_THREE,
                SIMPLE_QUESTION,
                SIMPLE_QUESTION,
                STAR);

但现在我看到它只能各有一个。从概念上讲,哪一个是解决这个问题的最佳结构。

问候 何塞

您可以使用 Enumeration -> Integer 类型的 Map,其中整数表示每个有多少。 google 番石榴 "MultiSet" 会为您完成此操作,并处理在尚无条目时向集合中添加枚举以及在离开 none 时删除枚举的边缘情况.

另一种策略是使用枚举序数索引。因为这个索引是唯一的,所以您可以使用它来索引一个大小为枚举大小的 int 数组,其中每个数组槽中的计数将指示您拥有的每个枚举的数量。像这样:

// initialize array for counting each enumeration type
// TODO: someone should double check every initial value will be zero
int[] cardCount = new int[CardEnum.values().length];
...

// incrementing the count for an enumeration (when we add)
cardCount[BEST_OF_THREE.ordinal()]++;
...

// decrementing the count for an enumeration (when we remove) 
cardCount[BEST_OF_THREE.ordinal()]--;
// DEBUG: assert cardCount[BEST_OF_THREE.ordinal()] >= 0
...

// getting the count for an enumeration 
int count = cardCount[BEST_OF_THREE.ordinal()];

...一段时间后

阅读了原始 post 下方解释 OP 所问内容的澄清评论后,很明显您最好使用每个元素一个条目的线性结构。我没有意识到你不需要关于你需要多少的详细信息。将它们存储在 MultiSet 或等效的计数结构中使得随机选择变得困难,因为您需要将从 [0, size) 中随机选择的索引归因于特定容器,这需要对数时间。

Sets 不允许重复,所以如果你想重复,你需要一个 List 或一个 Map。

如果您只需要重复项的数量,带有整数值的 EnumMap 可能是您的最佳选择。

如果顺序很重要,并且您需要快速访问每种类型的数量,您可能需要滚动自己的数据结构。

如果顺序很重要(但每个的数量不重要),那么 List 是可行的方法,具体实现取决于您将如何使用它。

  • LinkedList - 当列表开头有很多 inserts/removals 时最好。对 LinkedList 进行索引是非常昂贵的,应尽可能避免。如果通过将数据移到列表的前面来构建 List,但任何后来的添加都在最后,那么在构建初始 List 后转换为 ArrayList 是一个好主意 - 特别是如果预期在任何时候索引到 List .
  • ArrayList - 如有疑问,这是一个很好的起点。插入或删除项目需要移位,所以如果这是一个常见的操作,请查看其他地方。
  • TreeList - 这是一个很好的全能选项,并且在 List 中的任何位置插入和删除都不昂贵。这确实需要 Apache 公共库,并且使用的内存比其他库多一点。

Benchmarks,以及使用go生成它们的代码可以在这个gist.

中找到