【问题标题】:When to use queue over arraylist何时在 arraylist 上使用队列
【发布时间】:2013-06-30 11:11:51
【问题描述】:

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

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

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

【问题讨论】:

    标签: java arraylist queue


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

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

      值得注意的是,有些列表是队列。以LinkedList 为例。

      【讨论】:

      • 所以从这个意义上说,队列实际上是在限制 ArrayList 已经给我们的东西......它没有添加任何新功能。你可以用队列做什么,你可以用arraylist(a.k.a random access)做......但反之亦然
      • 这取决于你如何看待它。如果您试图在代码中实现一个杂货店行,ArrayList 会很烦人,因为它无法像Queue 那样方便地吸引下一个客户。你必须做if (!list.isEmpty()) list.remove(0);。我宁愿读/写queue.poll()
      • 为什么 Arraylist 不能轻易获得下一位客户?我们只需定义一个迭代器并执行 iter.next()
      • 这不像queue.poll()那么简单、富有表现力和可读性。您可以为此使用ArrayList。没有人说别的。它只是不适合这项工作。
      【解决方案3】:

      如果我给你一个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 提供的所有内容,这会让事情变得更容易思考。

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          【解决方案5】:

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

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

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

          【讨论】:

            【解决方案6】:

            是的!

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

            参考:docs.oracle.com

            【讨论】:

              【解决方案7】:

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

              除了将数据结构从arraylist更改为queue

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2016-11-22
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2015-07-23
                • 1970-01-01
                相关资源
                最近更新 更多