Java 中的 Ring Buffer

2022-08-31 11:35:11

我有一个流时间序列,其中我有兴趣保留最后4个元素,这意味着我希望能够弹出第一个元素,并添加到最后。从本质上讲,我需要的是一个环形缓冲区

哪种 Java 集合最适合此?向量?


答案 1

考虑Apache Common.CollectionsCircularFifoBuffer。与 Queue 不同,您不必维护基础集合的有限大小,并在达到限制后将其包装。

Buffer buf = new CircularFifoBuffer(4);
buf.add("A");
buf.add("B");
buf.add("C");
buf.add("D"); //ABCD
buf.add("E"); //BCDE

CircularFifoBuffer 将为您执行此操作,因为具有以下属性:

  • CircularFifoBuffer 是首个输入前出的缓冲区,具有固定大小,如果已满,则替换其最旧的元素。
  • CircularFifoBuffer的删除顺序基于插入顺序;元素的删除顺序与添加元素的顺序相同。迭代顺序与删除顺序相同。
  • add(Object)、BoundedFifoBuffer.remove() 和 BoundedFifoBuffer.get() 操作都在恒定时间内执行。所有其他操作以线性时间或更差的时间执行。

但是,您还应该考虑它的限制 - 例如,您无法将缺少的时间序列添加到此集合中,因为它不允许空值。

注意:使用当前常用集合 (4.*) 时,必须使用队列。喜欢这个:

Queue buf = new CircularFifoQueue(4);

答案 2

自番石榴15.0(2013年9月发布)以来,有驱逐队列

一个非阻塞队列,当尝试将新元素添加到队列中时,它会自动从队列的头部逐出元素,并且它已满。必须为逐出队列配置最大大小。每次将元素添加到完整队列时,队列都会自动删除其 head 元素。这与传统的有界队列不同,传统的有界队列在填满时会阻止或拒绝新元素。

此类不是线程安全的,并且不接受空元素。

使用示例:

EvictingQueue<String> queue = EvictingQueue.create(2);
queue.add("a");
queue.add("b");
queue.add("c");
queue.add("d");
System.out.print(queue); //outputs [c, d]

推荐