1

I'm reading J. Bloch's "Effective Java" and now I'm at the section about for-each vs for-loop. He mentioned three cases where we couldn't use the for-each loop and one of them is the following:L

Parallel iteration— If you need to traverse multiple collections in parallel, then you need explicit control over the iterator or index variable, so that all iterators or index variables can be advanced in lockstep (as demonstrated unintentionally in the buggy card and dice examples above).

The case is not quite clear to me, I can't imagine an example.

The first thought that popped into my head was that it was just about iterating the same collection in multiple threads but it's probably not what he meant. I don't see any restrictions preventing us from doing so (read-only). Actually:

public class MyRunnable implements Runnable{

    private Collection<String> col;

    //CTOR ommmited

    public void run(){
    for(String s : col){
       //print o, not modify
    }

}

Then we just start some threads with the same instance. So, we're not afraid of getting ConcurrentModificationException (JavaDocs) because we perform read-only access, even by multiple threads simultaneously.

What's wrong?

St.Antario
  • 26,175
  • 41
  • 130
  • 318

2 Answers2

6

I don't think he meant "in parallel" as in concurrently.

It is much simpler. Suppose you have two Collections and you want the same loop (not a nested loop) to iterate over both of them, taking the i'th element of each one in each iteration. You can't do that with the enhanced for loop, since it hides the indices and the iterator.

You must use the standard for loop (for ordered Collections) :

private List<String> one;
private List<String> two;

public void run(){
    for(int i = 0; i<one.size() && i<two.size();i++){
       // do something with one.get(i) and two.get(i)
    }
}

Or explicit Iterators (for un-ordered Collections) :

private Set<String> one;
private Set<String> two;

public void run(){
    for(Iterator<String> iterOne=one.iterator(),Iterator<String> iterTwo=two.iterator(); iterOne.hasNext()&&iterTwo.hasNext();){
       // do something with iterOne.next() and iterTwo.next()
    }
}
Eran
  • 387,369
  • 54
  • 702
  • 768
1

Parallel iteration— If you need to traverse multiple collections in parallel, then you need explicit control over the iterator or index variable, so that all iterators or index variables can be advanced in lockstep (as demonstrated unintentionally in the buggy card and dice examples above).

In plain English lockstep means at same time. It means you cannot iterate over more than one collection at same time using for-each. You will have to use separate iterators ( or for loop as shown by Eran) like below:

Iterator iterator1 = list1.iterator();
Iterator iterator2 = list2.iterator();
Iterator iterator3 = list3.iterator();
while (iterator1 .hasNext() && iterator2 .hasNext() && iterator3.hasNext()){
    Item i1 = iterator1 .next();
    Item i2 = iterator2 .next();
    Item i3 = iterator3.next();
    // rest of your code.
}
akhil_mittal
  • 23,309
  • 7
  • 96
  • 95