【问题标题】:Is there an efficient way to find out whether a queue item is "before" another one?有没有一种有效的方法来确定一个队列项目是否在另一个队列项目“之前”?
【发布时间】:2011-01-18 16:04:08
【问题描述】:

对于我的 Java 应用程序,我需要一些方法来确定 item1 在队列 Q 中是否在 item2 之前。当然,我可以只使用迭代器并开始遍历列表。但是,也许还有另一种方法可以发现这一点?

对于我的特定应用程序,我不能使用 LinkedList(它提供索引并可以轻松确定一个对象是否在另一个对象之前)。

【问题讨论】:

  • 可以使用队列以外的其他数据结构吗?
  • 我想使用队列,因为它的效率。见stackoverflow.com/questions/4724995/…
  • 好吧,也许在这种情况下最好使用 List list = Collections.synchronizedList(new LinkedList);而不是 ConcurrentLinkedQueue。如果您只需要队列的操作并且不尝试将其用作链表,则 ConcurrentLinkedQueue 可能会很快。

标签: java queue


【解决方案1】:

不,没有。根据定义,队列上的唯一操作是入队和出队,因此如果您的应用程序需要其他操作,那么队列不是正确的结构。

【讨论】:

    【解决方案2】:

    如果只需要判断 item2 是否已经在队列中, 您可以使用 java.util.LinkedHashMap 维护插入顺序并可用作 LIFO 队列。

    【讨论】:

    • 可以用作LIFO队列如何?它没有队列所需的任何 peek()、poll() 等方法。我能想到的唯一方法是使用map.entrySet().iterator().next(),但这非常低效!
    • 非常低效并不是我真正会使用的术语。在大多数用例中,这很好。列表中有多少条目,需要多长时间执行一次?除非您已经测量到 map.entrySet().iterator().next() 是您的代码中的问题,否则不要理会它。
    【解决方案3】:

    如果快速了解订单是一个大问题,请考虑向您的元素添加一个“订单”字段 - 并覆盖您的队列实现以填充该字段。

    我不会将 LinkedList 'index' 视为解决方案。它被实现为列表遍历。

    【讨论】:

    • 添加“订单”或“索引”字段需要更多空间,但速度要快得多。我认为权衡会没问题...
    【解决方案4】:

    我会保留一个从队列对象到整数的单独 HashMap,以及你曾经添加到队列中的对象总数的运行计数(所以当你插入对象 X 时,计数器意味着对象 X 是第 N 个插入的对象)。每次将对象添加到队列中时,将其作为键添加到 HashMap 中;该值是计数器的当前值。

    当您需要询问两个对象中的哪一个是第一个时,请在 HashMap 中查找它们并比较序数。哪个值低的先来。

    【讨论】:

      【解决方案5】:

      QueueCollection,因此您始终可以将其元素复制到另一个 Collection,以便您检索订单,例如

      List<YourType> copy = new ArrayList<YourType>(yourQueue);
      if(copy.indexOf(obj1)<copy.indexOf(obj2)){
          // some code here
      }
      

      当然,这是非常低效的,但它确实有效。 (您可能必须在执行此操作时同步队列)

      另一种方法是通过iterator()

      /**
       * Returns -1 if a occurs in the collection before b, 1 if b occurs before a
       * and 0 otherwise.
       */
      public static <T> int comparePositionInCollection(final T a,
          final T b,
          final Collection<T> collection){
      
          // todo: check for a==null, b==null, a.equals(b)
      
          final Iterator<T> iterator = collection.iterator();
          boolean foundA = false;
          boolean foundB = false;
          int result = 0;
          while(iterator.hasNext()){
              final T t = iterator.next();
              if(a.equals(t)){
                  if(foundB){
                      result = 1;
                      break;
                  }
                  foundA = true;
              } else if(b.equals(t)){
                  if(foundA){
                      result = -1;
                      break;
                  }
                  foundB = true;
              }
          }
          return result;
      }
      

      当然,您必须在访问迭代器之前同步队列,所以这也是非常低效的。

      【讨论】:

        【解决方案6】:

        LinkedList 是一个如此基本的类,很难想象我可以建议作为替代方案的东西。除了 ArrayList 支持随机访问并且可以更快地进行索引访问。然而,ArrayList 的效率不如队列。

        【讨论】:

          【解决方案7】:

          一般来说,队列将提供“窥视”操作,让您无需移除即可查看队列顶部的内容,但其他任何内容都需要不同的数据结构。否则,您将事物从队列中弹出并放到另一个队列中,直到您弄清楚为止,此时您需要重新排队您弹出的值。

          【讨论】:

            【解决方案8】:

            我推荐可以引用查找表的优先级队列。这样,您可以获得想要获得的元素的恒定性能,以及多项式插入成本。但是,如果您只是想进行比较,而不是找到最佳或最差优先级项目,这可能是专门为您的用途而设计的。但是,恒定的性能总是很好。然后您不必迭代数组,而只是查找。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-02-06
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多