首页 > 解决方案 > 在当前“while (iterator.hasNext())”循环中添加到迭代器

问题描述

在下面的代码中,我希望迭代运行 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");
    }
}

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

标签: java

解决方案


迭代器不应该已经知道它有更多的值要迭代吗?

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

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

它清楚地表明添加新元素不会影响您当前的循环流程。此外,如果您查看ListIterator实现的源代码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()返回下一个元素的位置。如您所见,两者cursorSubListsize 都增加了。所以,实际上,cursor被调整为跳过“旧”下一个位置,转而支持“新”下一个位置。每次add()调用,cursor都会相应地进行调整。要获得新元素,您应该使用previous()或重新开始循环。

此外,您的案例可以说明如下:

    cursor
      |
      V 
0     1
A 

添加和之后B,仍然指向一个不存在的元素:Ccursor

    cursor
      |
      V 
0 1 2 3
A B C

推荐阅读