【问题标题】:How to store a continuous stream of data so that you can access the most frequent values?如何存储连续的数据流,以便您可以访问最频繁的值?
【发布时间】:2014-12-29 23:35:57
【问题描述】:

来自证券交易所的股票更新流以股票代码、买入/卖出对(例如 YHOO,300)的形式出现(以非常高的速率)。我们必须始终显示在任何给定时间点按交易量计算的前 5 名交易量最高的股票。您将如何在内存中维护这些值?

我的想法是使用哈希图(Ticker->Volume)从提要 O(1) 更新我们的数据存储。然后根据交易量创建一个 Treemap 以显示前 5 个股票 O(1)。但是我想不出一种有效的方法来同步 Treemap 数据,因为 hashmap 中的值发生变化(非常频繁)。 有什么建议吗?

【问题讨论】:

  • “我们必须始终显示在任何给定时间点按交易量计算的前 5 名交易量最高的股票”您的窗口有多长?那天前五?过去 30 秒的前五名?
  • 在那个特定时刻的前五名(这经常变化)。您可以假设窗口为 1 秒。这是一个实时输入流。
  • 所以如果您在 3 秒前看到 1000 笔 ABC 交易和 1 秒前 XYZ 交易,您只想显示 XYZ?
  • 累计到一天结束。

标签: java data-structures


【解决方案1】:

如果交易数量是一个不断增加的累积值(看起来是这样),您可以保持:

  • 用于更新 O(1) 中交易数量的哈希图。
  • 由 5 个元素组成的简单数组,代表前 5 个股票代码及其交易量。

当一个新的更新到来时,你在 O(1) 中更新你的 hashmap,如果新的交易数量大到足以进入前 5 名,你也更新你的数组。检查数组并更新它可以在 O(1) 中完成。如果您不想将新卷与所有 5 个值进行比较,也可以使用二分搜索。

您不能比检查 log(5) 值的平均值更好。


如果交易数量不是越来越单调(这似乎不太可能,但如果您想考虑在有界时间间隔内完成的交易数量可能会发生),您还可以保持:

  • 您的 hashmap (Ticker -> Volume) 用于保存股票交易量的更新。
  • 对于前 5 名,您需要使用按容量递减排序的堆。

当更新到来时,您将:

  1. 从 O(1) 中的 hashmap 中获取代码的 Volume 的先前值(如果有)
  2. 在 O(log n) 中从堆中删除旧值(如果存在),通过旧卷查找
  3. 在堆中添加新值 O(log n)
  4. 在 O(1) 中更新哈希图中的新值

总复杂度为 O(log n),其中“n”是代码的数量。

即使你需要前 5 个代码,当一个代码的交易量下降时,你需要找到第 6 个元素将变为第 5 个元素,以及第 7 个元素......等等。 如果交易数量不是单调的,我认为你的复杂度不会比 O(log n) 低很多。

【讨论】:

    【解决方案2】:

    我们可以使用堆数据结构,其中根是交易量最大的股票。它的孩子是交易量第二大的孩子。 Root 的孙子将给 4 号和 5 号

    【讨论】:

    • 非常频繁地更新堆(因为提要以非常高的速率进入)效率不高。
    • 使用两个哈希图。一个将从提要中获取数据,另一个将每'x'秒更新一次treeMap或Heap。接下来'x'秒将输入提要切换到其他哈希图等......总是从堆/树图读取..当然统计现在延迟'x'秒
    【解决方案3】:

    这是我能想到的三个选项:

    • 使用bag 收集股票代码并偶尔对其进行迭代以计算频率。每天打烊后,重新设置袋子。这会起作用,但我怀疑你是否真的想要一次一天的统计数据。
    • 我想你会想要一个大约一分钟的时间来让这个工作真正发挥作用。在这种情况下,我会将交易保存在dequeue 中。在前面插入新交易,从后面修剪旧交易。偶尔冻结它以计算前五名。这行得通,但如果事情升温,可能很难预测您可能需要多大的队列。
    • 另一种方法是使用某种splay tree。但我不确定这是否比仅显示最近的五笔交易更好。

    【讨论】:

      【解决方案4】:
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-07
      • 1970-01-01
      • 2018-07-22
      • 2018-09-25
      • 2020-01-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多