Is there a way to access an iteration-counter in Java's for-each loop?
Is there a way in Java's for-each loop
for(String s : stringArray) {
doSomethingWith(s);
}
to find out how often the loop has already been processed?
Aside from using the old and well-known for(int i=0; i < boundary; i++)
- loop, is the construct
int i = 0;
for(String s : stringArray) {
doSomethingWith(s);
i++;
}
the only way to have such a counter available in a for-each loop?
No, but you can provide your own counter.
The reason for this is that the for-each loop internally does not have a counter; it is based on the Iterable interface, i.e. it uses an Iterator
to loop through the "collection" - which may not be a collection at all, and may in fact be something not at all based on indexes (such as a linked list).
There is another way.
Given that you write your own Index
class and a static method that returns an Iterable
over instances of this class you can
for (Index<String> each: With.index(stringArray)) {
each.value;
each.index;
...
}
Where the implementation of With.index
is something like
class With {
public static <T> Iterable<Index<T>> index(final T[] array) {
return new Iterable<Index<T>>() {
public Iterator<Index<T>> iterator() {
return new Iterator<Index<T>>() {
index = 0;
public boolean hasNext() { return index < array.size }
public Index<T> next() { return new Index(array[index], index++); }
...
}
}
}
}
}
The easiest solution is to just run your own counter thus:
int i = 0;
for (String s : stringArray) {
doSomethingWith(s, i);
i++;
}
The reason for this is because there's no actual guarantee that items in a collection (which that variant of for
iterates over) even have an index, or even have a defined order (some collections may change the order when you add or remove elements).
See for example, the following code:
import java.util.*;
public class TestApp {
public static void AddAndDump(AbstractSet<String> set, String str) {
System.out.println("Adding [" + str + "]");
set.add(str);
int i = 0;
for(String s : set) {
System.out.println(" " + i + ": " + s);
i++;
}
}
public static void main(String[] args) {
AbstractSet<String> coll = new HashSet<String>();
AddAndDump(coll, "Hello");
AddAndDump(coll, "My");
AddAndDump(coll, "Name");
AddAndDump(coll, "Is");
AddAndDump(coll, "Pax");
}
}
When you run that, you can see something like:
Adding [Hello]
0: Hello
Adding [My]
0: Hello
1: My
Adding [Name]
0: Hello
1: My
2: Name
Adding [Is]
0: Hello
1: Is
2: My
3: Name
Adding [Pax]
0: Hello
1: Pax
2: Is
3: My
4: Name
indicating that, rightly so, order is not considered a salient feature of a set.
There are other ways to do it without a manual counter but it's a fair bit of work for dubious benefit.