在当前的“ while(iterator.hasNext())”循环内添加到迭代器

时间:2019-12-28 23:47:40

标签: java

在下面的代码中,我希望迭代可以运行3次。最初,迭代器有1个“下一个”,但是在第一次迭代中,又向迭代器添加了两个值,因此应该再有两个“下一个”,即iterator.hasNext()应该为真。

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class Foo {

    public static void main(String[] args) {
        List<String> strings = new ArrayList<>();
        strings.add("A");
        ListIterator<String> iterator = strings.listIterator();
        int i = 0;
        while (iterator.hasNext()) {
            i++;
            String str = iterator.next();
            if (str.equals("A")) {
                iterator.add("B");
                iterator.add("C");
            }
          //  strings.remove(str);
          //  iterator = strings.listIterator();
        }
        System.out.println("The iteration was run " + i + " times");
    }
}

但是它只能运行一次。解决方法是,我可以从原始列表中删除当前迭代,然后重置迭代器(带注释的行)。但是为什么这是必要的?迭代器不应该已经知道它有更多的值可以迭代吗?

1 个答案:

答案 0 :(得分:1)

  

迭代器是否已经不知道它有更多的值要迭代?

不,不应该。如果您查看add() here的文档,则可以在其中找到以下句子

  

对next的后续调用将不受影响,而对previous的后续调用将返回新元素。 (此调用将对nextIndex或previousIndex的调用返回的值增加一个。)

很明显,添加新元素不会影响您当前的循环流。另外,如果您查看ListIterator的{​​{1}}实现的源代码:

ArrayList

... public E next() { checkForComodification(); int i = cursor; if (i >= SubList.this.size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (offset + i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; return (E) elementData[offset + (lastRet = i)]; } public void add(E e) { checkForComodification(); try { int i = cursor; SubList.this.add(i, e); cursor = i + 1; lastRet = -1; expectedModCount = ArrayList.this.modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } 变量指向cursor用于返回下一个元素的位置。如您所见,next()cursor的大小都会增加。因此,实际上,SubList已调整为跳过“旧”的下一个位置,而转向“新”的下一个位置。每次调用cursor时,add()都会相应地进行调整。要获取新元素,您应该使用cursor或重新开始循环。

此外,您的情况可以如下所示:

previous()

在添加 cursor | V 0 1 A B之后,C仍然指向不存在的元素:

cursor