为什么 Iterator 在 for 循环中不 "Move Next"

Why does the Iterator not "Move Next" in a for loop

我正在学习迭代,并使用以下私有 属性:

在我的 'CStickChart' Class 上实现了一个迭代器
  private List<CStick> cStickCollection = new ArrayList<CStick>();

然后将方法实现到 return CSticks:

  public Iterator<CStick> iterator() {
    return this.cStickCollection.iterator();
  }

现在,当我尝试遍历它时,我可以使用分配的 localCStick 来这样做,但是调用 CStickChart 迭代器上的 next() 方法并没有达到我的预期。我希望它能在我的 CStickChart 中给我下一个 CStick(因此,当我调用 getEPIC 时,我希望它能给我下一个 EPIC)。

// Print the EPIC out of the Array using the iterator
for (CStick localCStick : testCStickChart) {
  System.out.println(localCStick.getEPIC());
  //The below line doesn't return the next CStick and I'm not sure why
  System.out.println("next EPIC is " + testCStickChart.iterator().next().getEPIC());
}

请有人解释为什么不是这样(它总是 return 第一个 EPIC)

System.out.println("next EPIC is " + testCStickChart.iterator().next().getEPIC());

发生这种情况是因为在这一行中,您在循环的每次迭代中都获得了一个新的迭代器。每个新的迭代器再次从列表的开头开始。

因为您正在使用 .iterator() 获取 cStickCollection 的顶级迭代器。我认为您想在循环中使用相同的 iterator 位置,并在下一个元素处使用 peek 。你不能用 for-each 循环做到这一点,你也不能用 Iterator 通常做到这一点(因为它们没有实现 peek)。

相反,您可以在 cStickCollection 上使用传统的 for 循环,例如

for (int i = 0, len = cStickCollection.size(); i < len; i++) {
    CStick localCStick = cStickCollection.get(i);
    System.out.println(localCStick.getEPIC());
    if (i + 1 < len) { // <-- check that there is a "next"
        System.out.println("next EPIC is "+cStickCollection.get(i+1).getEPIC());
    }
}

每次在该循环内调用 testCStickChart.iterator() 时,都会创建一个新的迭代器对象。所以每次调用 next() 都是在一个新的迭代器对象上执行的,返回第一个对象。你想要做的是在循环之前声明一个新的 Iterator<CStick> 并在循环中使用它,就像这样:

Iterator<CStick> it = testCStickChart.iterator();
// Print the EPIC out of the Array using the iterator
for (CStick localCStick : testCStickChart) {
    System.out.println(localCStick.getEPIC());
    //The below line doesn't return the next CStick and I'm not sure why
    System.out.println("next EPIC is " + it.next().getEPIC());
}

听起来您不想使用增强型-for 结构。原因:具有可迭代实体 will use the iterator provided internally 的增强型 for,并且只会向前推进。

这也意味着在该循环内对 iterator 的任何调用都会产生一个从迭代的 开始 处开始的迭代器。

因此,您有两个选择 - 都涉及放弃增强型-for:

  • 使用带索引的标准 for 循环在列表中前后移动,或者
  • 使用 List 提供的 ListIterator 以非常无缝的方式前后移动。

这是一个使用整数的示例 - 请注意,每次我推进迭代器时,我都必须将它移回之前的位置,这样我就不会重复推进它。另外,一旦我们 运行 没有元素,我就有条件跳出循环。

List<Integer> integerList = new ArrayList<Integer>() {{
    add(1);
    add(2);
    add(3);
    add(4);
    add(5);
    add(6);
    add(7);
    add(8);
    add(9);
    add(10);
}};

for (ListIterator<Integer> iterator = integerList.listIterator(); iterator.hasNext(); ) {
    int value = iterator.next();
    int nextValue = Integer.MIN_VALUE;
    if (iterator.hasNext()) {
        nextValue = iterator.next();
        // Reset the state of the iterator
        iterator.previous();
    }

    System.out.println("Value = " + value);
    if(nextValue != Integer.MIN_VALUE) {
        System.out.println("Next value = " + nextValue);
    }
}