2016-01-21 99 views
0

晚上好,的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; 
+0

@redFIVE增强的for循环不允许在迭代期间更新集合,这是OP正在做的事情。 OP正在做错误的方式。 – Andreas

+0

你正在使用它来回避实现中的迭代器。通过创建'int i'变量并通过索引访问列表,你已经打破了'Iterator'的整个想法。另外,如果你想删除一个元素,有一个'Iterator#Remove()'方法。 – Draco18s

回答

1

为什么要删除和添加,何时可以简单地替换该值?您应该使用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实现方式中,例如如果ListLinkedList,索引版本性能将会很差。

1

哈瓦一看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

0

其中用于收集得到Iterator在代码点,由像调整大小的操作的结构修饰,添加或删除到集合不recommende当如d。如果您需要该功能,您可以尝试使用CopyOnWriteArrayList