21

在 ArrayList 上使用 Queue 的一个基本论点是 Queue 保证 FIFO 行为。

但是,如果我将 10 个元素添加到 ArrayList,然后从第 0 个元素开始遍历元素,那么我将按照添加元素的顺序检索这些元素。所以本质上,这保证了 FIFO 行为。

与传统的 ArrayList 相比,Queue 有什么特别之处?

4

7 回答 7

17

您可以在此处查看 javadoc。主要区别在于List允许您随时查看任何元素。队列只让您查看“下一个”队列。

将其视为真正的队列或杂货店收银机的队列。您不会要求中间或最后的人接下来付款,您总是会问在前面/等待时间最长的人。

值得注意的是,有些列表是队列。例如,查看LinkedList

于 2013-07-02T22:05:56.663 回答
16

如果我给你一个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必须提供的东西,这会使事情变得更容易考虑。

于 2013-07-02T22:24:14.190 回答
7

与 ArrayList 相比,对队列施加的限制(FIFO,无随机访问)允许更好地优化数据结构,具有更好的并发性,并且在需要时成为更合适和更简洁的设计。

关于优化和并发,想象一下生产者填充队列而消费者消费它的常见场景。如果我们为此使用 ArrayList,那么在幼稚的实现中,每次删除第一个元素都会导致 ArrayList 上的移位操作,以便向下移动所有其他元素。这是非常低效的,尤其是在并发实现中,因为列表将在整个移位操作期间被锁定。

在设计方面,如果要以 FIFO 方式访问项目,则使用队列会自动传达该意图,而列表则不会。这种清晰的沟通有助于更轻松地理解代码,并可能使代码更健壮且无错误。

于 2013-07-02T23:57:20.140 回答
1

不同之处在于,对于队列,您可以保证按 FIFO 顺序取出元素。对于 ArrayList,您不知道元素的添加顺序。根据您使用它的方式,您可以对 ArrayList 强制执行 FIFO 排序。我还可以为 Queue 设计一个包装器,让我可以取出我想要的任何元素。

我要说明的一点是,这些课程旨在擅长某些方面。您不必为此使用它们,但这就是它们的设计和优化目的。队列非常擅长添加和删除元素,但如果您需要搜索它们则不好。另一方面,ArrayLists 添加元素有点慢,但允许轻松随机访问。您不会在您编写的大多数应用程序中看到它,但是选择一个而不是另一个通常会降低性能。

于 2013-07-02T22:43:59.123 回答
1

是的!

我会在队列中使用 poll() 和 peek() 方法,它们返回值以及 remove ,分别检查 head 元素。此外,如果操作失败并且不抛出异常,这些方法为您提供特殊值 null使用 remove() 方法将抛出 nosuchelement 异常。

参考:docs.oracle.com

于 2015-12-03T11:50:28.747 回答
0

例如,Queue方法poll()remove()检索元素并将其从队列中删除。

Queue接口 ( )的某些实现PriorityQueue允许为元素设置优先级,并根据该优先级检索它们。在最后一种情况下,它不仅仅是一种 FIFO 行为。

于 2013-07-02T22:05:44.247 回答
0

考虑随机进程随机更新数组列表并且我们应该在 fifo 中处理它们的情况?

绝对没有办法做到这一点,只能将数据结构从 arraylist 更改为 queue

于 2017-05-09T18:48:54.703 回答