是否有任何Java库提供随机访问队列实现?

时间:2009-11-05 18:26:07

标签: java collections queue random-access circular-buffer

我正在使用Java在事件流上实现一个滑动窗口。 所以我想要一个允许我执行以下操作的数据结构:

  1. 在发生新事件时添加到数据结构的末尾;

  2. 在处理旧事件时从数据结构的开头删除;

  3. 获取标准随机访问(size()get(i))到数据结构的元素;通常,典型的List“阅读”操作;

  4. 对所有上述操作都有效;

  5. 无界限。

  6. 无需其他访问权限。并且不需要线程安全。

    我目前正在使用ArrayList执行此操作,以便开始运行。但我想要更高效的东西;使用remove(0)时,ArrayList方法(上面的2.)效率很低。

    数字1.和2.是标准Queue - 样式的操作。但是,JDK中Queue的实现(例如ArrayDeque)不允许3中的get(i)

    所以,我想知道是否有任何具有这样的实现,并且适合商业用途。

    如果没有,我想我会写自己的......

8 个答案:

答案 0 :(得分:4)

似乎是Circular Buffer的任务 - 只要队列具有固定容量就可以了。我不知道有任何标准的实现。但这里是a nice recipe to roll your own

答案 1 :(得分:4)

我遇到了这个问题并试图通过复制ArrayDeque的源代码并添加类似的内容来解决它:

E get(index){ return elements[(head + index) % size];}

答案 2 :(得分:3)

如果你有一个足够大的数组,你可以实现一个带有基本数组的队列,只需使用一个索引作为列表的头部,并使用mod运算符,这样你就可以在需要时回滚。

所以,你基本上有一个支持插入和删除函数的循环数组。

<强>更新

将数组复制到一个更大的数组是一个快速的操作,所以当接近结尾时,可能只是加倍,并且只是复制数组,作为插入操作的一个步骤。总体而言,您仍然可以非常快速地访问,因为常规不应该是增加和复制。

答案 3 :(得分:2)

事件进出这个队列的速度有多快?

一方面,你可以拥有一个“足够大”的循环缓冲区。

虽然它在技术上是“有限的”,但你可以通过在必要时增长来使其“无限制”。

出于同样的原因,当它“安静”时,你可以在整体容量方面“缩小”它。

但是,对于许多应用程序,100,1000甚至10000项容量的循环缓冲区实际上是无限制的。

答案 4 :(得分:1)

只是把它扔到那里作为滚动你自己的替代方案,所以请带着一点点盐:取决于您需要随机访问get(i)的频率以及您需要的性能(以及它有多大)您的队列大小通常是),当您需要访问元素时,可以始终使用ArrayDeque.toArray()[i]toArray()使用System.arraycopy()封面,对于小型队列大小和偶尔使用,应该非常快。有助于理解为什么需要随机访问队列以及需要多长时间 - 可能有一种不同的方法来实现你的算法。

答案 5 :(得分:1)

如果它真的必须是无界的,那么像ConcurrentSkipListMap这样的东西可能很有用,如果你为每个事件分配一个递增序列以用作地图中的键。 它提供了pollFirst / LastEntry等方法。 如果你可以牺牲它的无界性质,那么你可能需要一个环形缓冲区。

答案 6 :(得分:0)

我能想到的唯一可以实现这种接口的库是LinkedList,但坦率地说我不确定性能特征是什么。

答案 7 :(得分:0)

二项式堆可以有O(1)摊销的插入和O(log n)摊销删除min;我相信它也可以有O(log ** 2 n)摊销的随机访问。 Queue-push会将元素插入堆中,并将连续的整数作为键。

使用rbtree,您可以对O(log n)进行队列推送,对所有插入,删除min和随机访问都是悲观的。这是因为树将有一个连续的整数集作为键,而队列的第k个元素将是树中带有第k个键的元素。