【问题标题】:Circular Buffer HashSet in JavaJava中的循环缓冲区HashSet
【发布时间】:2022-11-14 05:12:01
【问题描述】:

是否可以创建一个HashSet<Long>,它将像具有固定大小的缓冲区一样工作,并且仍然具有O(1) 复杂性(或至少相似)?

我需要一个 HashSet 来一个一个地保存大量的 Longs(没有重复),然后尽可能快地通过contains(Long) 读取它。

我的用例是 1 天内大约 1000 万长。这就是为什么我需要一个有限制的循环缓冲区。然后,我可以将 HashSet 的大小限制为例如 100 万个,并且当我在集合中超过 100 万个项目时开始覆盖旧项目。

我试过的:HashMap<Int, Long>Int currentIndex, Int maxItems 很有价值。当 currentIndex > maxItems 时,我能够开始覆盖旧值...可悲的是,在这个 HashMap 中按值搜索很慢。

【问题讨论】:

  • 有了这样的分数你应该知道发布你的代码,给出实际和预期的结果......

标签: java dataset


【解决方案1】:

已经提出了类似的问题。你看了吗? Java Collection for special scrolling, circular queue

【讨论】:

    【解决方案2】:

    我不确定这些 long 是时间戳还是只是 ID。不管怎样,HashSet 不能做你想做的事。这是错误的数据存储。 HashSet 具有任意顺序;询问一个哈希集“它里面的所有 long 中最低的是什么”不是它可以在不迭代整个事物的情况下回答的问题,您也不能要求“我放入的第一个”。

    你有几个解决方案:

    • 树集。从技术上讲,一切都是O(logn),但每秒约 120 个项目(每 24 小时 1000 万个归结为大约)什么都不是,因此,O(logn) 在这里的所有意图和目的都相当于 O(1)。 TreeSets 'self sort' - 询问一个树集的最短时间是很快的。 (100 万个项目?大约需要 20 次查找,这就是 O(logn) 的意思——每个数量级只增加 1 次查找。1 亿个项目或多或少只需要 25 次查找)。如果这些 long 是时间戳,并且一旦树集的大小达到 100 万,您想清除“最旧的”,TreeSet 可以做到这一点,而且可以很快做到。
    • LinkedHashSet - 这是一个双重数据结构,让您既可以按键查找,也可以“获取最旧的条目”。虽然因此内存负载较大,但速度为 O(1):向 LinkedHashMap/Set 询问“最旧”条目与向 TreeSet 询问最小键一样即时。

    如果您在它们发生时将它们放入地图中并使用时间戳作为键,那么任何一个都可以 - 因为“数据结构中最旧的”和“具有最低键的数据结构中的条目”归结为相同事物。

    但仍有更多数据类型可能符合条件。 ArrayDeque 是一个循环数据结构。它与ArrayList 非常相似,除了在开始数据结构就像添加/删除一样即时在最后.通过键值查找很慢,就像使用数组列表一样 - 如果这是您的需要,请查看 TreeSet 或 LinkedHashSet/Map。

    或者,您直奔主题并使用guava's Cache 机制。它是专门为这项工作设计的,并且有一个与之匹配的 API,包括能够告诉数据存储本身清除最旧的成员,使其永远不会超过 100 万,您甚至可以询问集合对象本身希望此缓存清理发生在“写入时”(即,如果已满,则删除最旧的条目)或“访问时”(即,如果已满,则删除未查找时间最长的条目 - 也就是说,任何查找也会“刷新” '它,有效地)。

    【讨论】:

      猜你喜欢
      • 2016-06-11
      • 2019-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多