类似于 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.
中找到
我需要一些结构来存储 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.
中找到