【问题标题】:Java-Collection: What collection to use is this very specific case?Java-Collection:这个非常具体的案例要使用什么集合?
【发布时间】:2018-06-19 11:01:11
【问题描述】:

我有以下场景,正在寻找“最佳”实现:

  1. 我想将项目存储在java.util.Collection 中以实现接口
  2. 保证所有物品都有唯一的hashCode
  3. 我知道要存储的项目的最大数量 n(最大 capacity 在初始化时已知)
  4. hashCode0n 之间
  5. 顺序不重要,不需要重复(需要Set-properties)
  6. 项目可以添加,但永远不会被删除
  7. contains 的性能非常重要(期望:O(1),至少O(log_n)

我的第一个想法是使用new HashSet<item>(n+1, 1.0),但在阅读后发现它对项目的hashCode 应用了一个内部哈希函数,因此即使hashCodes 是独一无二的hachCode <= n

我的第二个想法是使用原生数组 (new item[n]) 并使用 hashCode 作为索引。这似乎是性能最好的实现,但我的界面需要java.util.Collection,并且该集合将与containsadd 一起使用,这与第二种方法的好处不兼容。

是我遗漏了什么,还是我必须接受HashSet 的开销和冲突才能获得最佳性能?

【问题讨论】:

  • 使用哈希集,除非您真正观察到性能问题,否则不要担心性能。
  • 如果您担心哈希冲突,您就不能定义自己的hashCode() 方法吗?而且,鉴于哈希冲突很少见 - 为什么它甚至重要?
  • 我只会选择 HashSet。它满足您指定的所有要求。没有重复,O(1) 检索。此外,由于它是一个标准的 java 类,因此您将数据操作到不同的结构/顺序等将比您提供自己的自定义实现更容易。
  • 如果您事先知道集合中将包含哪些元素,您可以尝试提出一个 hashCode 函数,该函数为每个元素提供唯一的结果;否则,碰撞只是生活中的事实。
  • @vikingsteve @Maurice 请参阅我的问题的第 2 点。我的item 类的hashCode() 方法不是问题,但在内部HashSet 使用另一种散列算法根据项目的hashCode 计算存储桶。这确保了即使hashCodes 实现不佳的对象也可以被有效地存储。它基本上会导致很少的碰撞,但几乎从来没有。

标签: java collections hashset


【解决方案1】:

使用HashSet 仍然会给您带来良好的性能,但鉴于您描述的特定要求(假设n 不太大),您可以创建自己的Set 接口的“ArraySet”实现:

  • 它将有一个长度为n+1 的后备数组来存储数据。
  • contains 将使用元素的hashCode 来查找与hashCode() 匹配的索引是否具有非空值。
  • add 将使用已添加元素的 hashsCode 来查找应添加元素的数组的索引。
  • 任何其他必需的方法都将以类似方式实现。

这个解决方案可能比HashSet 稍微高效一些,因为它包含的开销更少。但是,如果n 很大,则内存使用量会很大。

【讨论】:

    【解决方案2】:

    鉴于需求,我建议你使用HashSet。它会表现得更好。正如您提到的,最大元素数和最大容量 Set 的大小相同。此外,每个元素都有一个唯一的哈希码。在这种情况下,哈希键冲突很少发生变化。所以不用担心 contains 功能。使用提到的数据集,包含 将在 O(1) 中执行。同样,add 也将按恒定顺序执行。即 O(1)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-14
      • 2012-11-22
      • 1970-01-01
      相关资源
      最近更新 更多