在 ArrayList 上使用 Queue 的一个基本论点是 Queue 保证 FIFO 行为。
但是,如果我将 10 个元素添加到 ArrayList,然后从第 0 个元素开始遍历元素,那么我将按照添加元素的顺序检索这些元素。所以本质上,这保证了 FIFO 行为。
与传统的 ArrayList 相比,Queue 有什么特别之处?
您可以在此处查看 javadoc。主要区别在于List
允许您随时查看任何元素。队列只让您查看“下一个”队列。
将其视为真正的队列或杂货店收银机的队列。您不会要求中间或最后的人接下来付款,您总是会问在前面/等待时间最长的人。
值得注意的是,有些列表是队列。例如,查看LinkedList。
如果我给你一个Queue
实例,那么你就会知道通过迭代调用remove()
你会以 FIFO 顺序检索元素。如果我给你一个ArrayList
例子,那么你不能做这样的保证。
以下面的代码为例:
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(5);
list.add(4);
list.add(3);
list.add(2);
list.add(1);
list.set(4,5);
list.set(3,4);
list.set(2,3);
list.set(1,2);
list.set(0,1);
System.out.println(list);
如果我现在给你这个列表,那么我从 0 迭代到 4,你不会得到 FIFO 顺序的元素。
另外,我想说另一个区别是抽象。有了一个Queue
实例,您就不必担心索引,如果您不需要所有ArrayList
必须提供的东西,这会使事情变得更容易考虑。
与 ArrayList 相比,对队列施加的限制(FIFO,无随机访问)允许更好地优化数据结构,具有更好的并发性,并且在需要时成为更合适和更简洁的设计。
关于优化和并发,想象一下生产者填充队列而消费者消费它的常见场景。如果我们为此使用 ArrayList,那么在幼稚的实现中,每次删除第一个元素都会导致 ArrayList 上的移位操作,以便向下移动所有其他元素。这是非常低效的,尤其是在并发实现中,因为列表将在整个移位操作期间被锁定。
在设计方面,如果要以 FIFO 方式访问项目,则使用队列会自动传达该意图,而列表则不会。这种清晰的沟通有助于更轻松地理解代码,并可能使代码更健壮且无错误。
不同之处在于,对于队列,您可以保证按 FIFO 顺序取出元素。对于 ArrayList,您不知道元素的添加顺序。根据您使用它的方式,您可以对 ArrayList 强制执行 FIFO 排序。我还可以为 Queue 设计一个包装器,让我可以取出我想要的任何元素。
我要说明的一点是,这些课程旨在擅长某些方面。您不必为此使用它们,但这就是它们的设计和优化目的。队列非常擅长添加和删除元素,但如果您需要搜索它们则不好。另一方面,ArrayLists 添加元素有点慢,但允许轻松随机访问。您不会在您编写的大多数应用程序中看到它,但是选择一个而不是另一个通常会降低性能。
是的!
我会在队列中使用 poll() 和 peek() 方法,它们返回值以及 remove ,分别检查 head 元素。此外,如果操作失败并且不抛出异常,这些方法为您提供特殊值 null使用 remove() 方法将抛出 nosuchelement 异常。
参考:docs.oracle.com
例如,Queue
方法poll()
和remove()
检索元素并将其从队列中删除。
Queue
接口 ( )的某些实现PriorityQueue
允许为元素设置优先级,并根据该优先级检索它们。在最后一种情况下,它不仅仅是一种 FIFO 行为。
考虑随机进程随机更新数组列表并且我们应该在 fifo 中处理它们的情况?
绝对没有办法做到这一点,只能将数据结构从 arraylist 更改为 queue