【问题标题】:ListIterator allocation in JavaJava中的ListIterator分配
【发布时间】:2016-03-08 07:34:18
【问题描述】:

我有一个实时程序运行一个连续的 while 循环...

示例:

while(true)
{


}

在那个循环中我有一个for(MyObject o: myobjects) 循环。当我运行我的代码时,我看到 while 循环的每次迭代都会创建一个新的迭代器来循环我的 LinkedList,称为 myobjects

在不让 Java 每次都创建 ListIterator 的情况下迭代 LinkedList 的更好方法是什么?

【问题讨论】:

    标签: java android for-loop foreach iterator


    【解决方案1】:

    在不让 Java 每次都创建 ListIterator 的情况下迭代 LinkedList 的更好方法是什么?

    “更好”是非常情境化的。您应该考虑您现在的行为是否真的是一个问题,因为您所描述的是关于该工作的最简单的 Java 代码。

    如果您确实需要专门迭代 LinkedList(而不是 ArrayList),并且您不想每次都创建新的 ListIterator,那么您最好的选择可能是预先创建一个ListIterator,并在每次迭代中重用它:

    ListIterator<MyObject> iterator = myobjects.listIterator();
    
    while (true) {
        // Return to the beginning of the list:
        while (iterator.hasPrevious()) {
            iterator.previous();
        }
    
        // The desired iteration:
        while (iterator.hasNext()) {
            MyObject o = iterator.next();
            // do something with o
        }
    }
    

    但是请注意,如果基础列表被修改,这会给您带来麻烦。任何这样的修改都会使ListIterator 失效(它的方法应该开始抛出ConcurrentModificationExceptions)。在您的原始代码中,这只会影响外循环的一次迭代,但如果您重用迭代器,那么您可能需要对这种情况进行不同的处理。如果列表在外循环的其他地方被修改,那么重复使用相同的迭代器是正确的。

    另一方面,如果您可以确定您有一个RandomAccess 列表,例如ArrayList,那么您可以完全避免使用迭代器,而只需按索引进行迭代:

    while (true) {
    
        // The desired iteration:
        for (int i = 0; i < myobjects.size(); i += 1) {
            MyObject o = myobjects.get(i);
            // do something with o
        }
    }
    

    如果您有或可能有LinkedList,请不要这样做,因为这会将@987654332 的迭代成本从 O(n) 增加到 O(n2) @s 和类似的顺序访问列表。

    【讨论】:

      【解决方案2】:

      LinkedList 的源代码说正在创建一个新的迭代器。如果您的列表是动态的,您将需要一个新的迭代器,因为它会变得陈旧。

      但是,我相信如果你的列表是一个常数,你最好运行一个普通的 for 循环。

      `int length = myobjects.size();
       for (int i=0; i < length; i++)
       {
            //access here
       }`
      

      【讨论】:

        【解决方案3】:

        新的迭代器是按设计给出的。阅读this。每次调用 iterator() 方法时,它都会为您提供一个新的迭代器,并且它不维护状态。

        迭代器代码:

        public ListIterator<E> listIterator(final int index) {
            rangeCheckForAdd(index);
        
            return new ListItr(index);
        }
        

        【讨论】:

        • 根据我对 LinkedLists 如何在后台工作的理解,为什么不只维护一个名为“traverse”的指针,并在开始时将其分配给“头”节点,当它到达'tail' 节点,停止迭代,然后重复该过程......换句话说,为什么每次都重新创建 'traverse' 指针?
        • 你可以保持状态。但是他们不能为你维护它。如果您想遍历列表以查找其中的所有重复项,请考虑一下?如果你的迭代器是由内部代码维护的,你会怎么做?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-03-21
        • 1970-01-01
        • 1970-01-01
        • 2016-09-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多