【问题标题】:FIFO queue in JDK [duplicate]JDK中的FIFO队列[重复]
【发布时间】:2019-11-02 02:49:11
【问题描述】:

我想要一个 FIFO 的有限队列。因此,如果队列的最大大小超过,则删除第一个元素。

带有 google 集合的 FIFO 队列:

Queue<Integer> fifo = EvictingQueue.create(2); 
fifo.add(1); 
fifo.add(2); 
fifo.add(3); 
System.out.println(fifo);  // prints [2, 3]

带有 apache 集合的 FIFO 队列:

// FIFO-queue works with apache collections
Queue<Integer> fifo2 = new CircularFifoQueue<>(2);
fifo2.add(1);
fifo2.add(2);
fifo2.add(3);
System.out.println(fifo2); // prints [2, 3]

带有 JDK 集合的 FIFO 队列:

Queue<Integer> fifo3 = new ArrayBlockingQueue<>(2);
fifo3.offer(1);
fifo3.offer(2);
fifo3.offer(3);
System.out.println(fifo3); // prints [1, 2]

ArrayBlockingQueue 不能作为 FIFO 工作,它只会在队列已满时停止插入元素。

是否有类似EvictingQueueCircularFifoQueue 的JDK FIFO 队列?

如果 JDK 不提供类似的功能,我应该选择哪一个:EvictingQueueCircularFifoQueue? 哪个实施得更好?

(请不要提供fifo队列的示例实现,我要使用lib,最好只有JDK)

【问题讨论】:

  • ArrayBlockingQueue&lt;&gt;(2, true) 呢?这将是先进先出。
  • @anatoli 不,不起作用。它是prints [1, 2] 而不是[2, 3]

标签: java collections


【解决方案1】:

如果您看到 ArrayBlockingQueue 的 offer 实现,它有一行,所以值 3 甚至没有附加到 items 数组。

if (count == items.length)
  return false;

所以你可以这样做:

static void append(Queue<Integer> fifo, int i) {
  if (!fifo.offer(i)) {
      fifo.poll();
      fifo.offer(i);
  }
}

// in main:
Queue<Integer> fifo3 = new ArrayBlockingQueue<>(2);
append(fifo3, 1);
append(fifo3, 2);
append(fifo3, 3);
System.out.println(fifo3); // prints [2, 3]

【讨论】:

  • 看来,JDK 没有提供队列实现,如果超过大小,则会自动删除第一个元素。您的append()CircularFifoQueueEvictingQueue 的最终结果是相同的,但我仍然不知道它们之间的陷阱......都是有界队列和阻塞队列,所以我想,我会使用你的append()-方法而不是其他方法..谢谢!
【解决方案2】:

JDK 确实提供了一个 FIFO 队列,但没有大小限制(因此没有循环队列),它是 LinkedList 类。

点赞javadoc says about Queue interface

队列通常(但不一定)以 FIFO(先进先出)方式对元素进行排序。 [...] 无论使用什么排序,队列的头部都是通过调用 remove() 或 poll() 删除的元素。 在 FIFO 队列中,所有新元素都是插入到队列的尾部。其他类型的队列可能使用不同的放置规则。 每个队列实现都必须指定其排序属性。

LinkedList doc我们知道add方法“将指定元素追加到这个列表的末尾”,所以调用add/offer会在队列尾部插入一个元素,而remove/poll将从头部获取一个元素。

所以,如果你不需要一个固定大小的队列,你可以使用:

Queue<Type> q = new LinkedList<Type>();
q.add(elem1);
q.add(elem2);
q.add(elem3); // [elem1, elem2, elem3]
q.remove(); // [elem2, elem3]

否则,您可以只使用 Robert 实现。

【讨论】:

  • 很高兴知道,谢谢。就我而言,我需要一个有界队列。然而,奇怪的是没有队列实现提供获取其尾部(=队列中的最后一个元素)的方法。
  • Queue 接口不提供它,但 LinkedList 提供。 remove()/poll() 将从头部提取元素,而remove​(int index) 将从任意位置提取元素;如果需要快速提取尾部,可以使用pollLast()
  • @nimo23 FIFO/Queue 显然是一种只能在一端插入并从另一端移除的数据结构。如果你想要一个也允许获取最后一个元素的数据结构,你正在寻找一个Deque,它代表“双端队列”。当您点击链接时,您会看到有多种实现,我更喜欢 ArrayDeque 而不是 LinkedList,尤其是因为您事先知道预期的容量。当严格执行最大大小时,它一个循环fifo队列。
猜你喜欢
  • 2015-01-26
  • 2023-04-03
  • 2017-04-12
  • 2019-04-11
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多