为什么 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);
}
}
我正在学习迭代,并使用以下私有 属性:
在我的 '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);
}
}