的Java迭代器,相较于循环
问题描述:
晚上好,的Java迭代器,相较于循环
我想呼吁的ArrayList内的每个像素的“ricolora法”(修改像素的颜色),第一种方法(具有迭代)不起作用。
它给了我一个例外(java.lang.reflect.InvocationTargetException)。
第二种方法(for循环)工作得很好。你能帮我理解为什么第一种方法不起作用,我认为for循环和迭代器几乎是一回事。
谢谢你的帮助。
public class DisegnoManoLibera {
protected final ArrayList<Pixel> pixel;
final public void ricolora(Color c) {
Iterator<Pixel> it = this.pixel.iterator();
int i=0;
while(it.hasNext()){
Pixel pi =(Pixel) it.next();
Pixel gi = new Pixel(pi.getX(), pi.getY(), c);
pixel.remove(i);
pixel.add(i, gi);
i++;
}
}
final public void ricolora(Color c) {
for(int i=0; i<this.pixel.size();i++){
Pixel pip = pixel.get(i);
Pixel gin = new Pixel(pip.getX(), pip.getY(), c);
pixel.remove(i);
pixel.add(i, gin);
}
}
public class Pixel {
final int x;
final int y;
final Color c;
答
为什么要删除和添加,何时可以简单地替换该值?您应该使用List.set(int index, E element)
或ListIterator.set(E e)
。
在迭代集合时,通常不允许修改集合,除非通过迭代器。大多数集合对象的迭代器都实现了故障快速逻辑,以防止意外违反该规则。专门为多线程并发访问而设计的集合是个例外。
所以,如果使用Iterator
,只能通过该迭代器进行修改。
// Using ListIterator
public final void ricolora(Color c) {
for (ListIterator<Pixel> it = this.pixel.listIterator(); it.hasNext();) {
Pixel pi = it.next();
Pixel gi = new Pixel(pi.getX(), pi.getY(), c);
it.set(gi);
}
}
// Using index
public final void ricolora(Color c) {
for (int i = 0; i < this.pixel.size(); i++) {
Pixel pi = this.pixel.get(i);
Pixel gin = new Pixel(pi.getX(), pi.getY(), c);
this.pixel.set(i, gin);
}
}
Iterator
的版本通常是优选的,因为它表现良好不管List
实现方式中,例如如果List
是LinkedList
,索引版本性能将会很差。
答
哈瓦一看here,这说明了什么歧方法是在那里通过列表进行迭代。 您看到您在使用迭代器时(您的pixel.remove(i);
和pixel.add(i, gi);
)不应该操纵底层列表。
作为替代方案,您可以使用ListIterator,它具有remove()和add()方法(或者在您的情况下set()来替换元素)。
for (ListIterator<E> iter = list.listIterator(); iter.hasNext();) {
E element = iter.next();
// 1 - can call methods of element
// 2 - can use iter.remove() to remove the current element from the list
// 3 - can use iter.add(...) to insert a new element into the list
// between element and iter->next()
// 4 - can use iter.set(...) to replace the current element
// ...
}
并再次引用其他职位:
注:由于@amarseillan指出,这种形式是用于遍历列表,因为get方法的实际执行情况可能并不糟糕的选择作为有效利用的Iterator
@redFIVE增强的for循环不允许在迭代期间更新集合,这是OP正在做的事情。 OP正在做错误的方式。 – Andreas
你正在使用它来回避实现中的迭代器。通过创建'int i'变量并通过索引访问列表,你已经打破了'Iterator'的整个想法。另外,如果你想删除一个元素,有一个'Iterator#Remove()'方法。 – Draco18s