views:

1822

answers:

9

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 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?

+2  A: 

If you need a counter in an for-each loop you have to count yourself. There is no built in counter as far as I know.

EricSchaefer
(I've fixed that bug in the question.)
Tom Hawtin - tackline
Check again. There is the same bug in the second code snippet...
EricSchaefer
+4  A: 

You need to run your own counter thus:

int i = 0;
for(String s : stringArray) {
    doSomethingWith(s,i);
    i++;
}
paxdiablo
A: 

No, and it hurts.

Yoni Roit
+15  A: 

Yes, you'll have to 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).

Michael Borgwardt
+6  A: 

I'm afraid this isn't possible with foreach. But I can suggest you a simple old-styled for-loops:

 List<String> l = new ArrayList<String>();

 l.add("a");
 l.add("b");
 l.add("c");
 l.add("d");

 // the array
 String[] array = new String[l.size()];

 for(ListIterator<String> it =l.listIterator(); it.hasNext() ;)
 {
  array[it.nextIndex()] = it.next();
 }

Notice that, the List interface gives you access to it.nextIndex().

(edit)

To your changed example:

 for(ListIterator<String> it =l.listIterator(); it.hasNext() ;)
 {
  int i = it.nextIndex();
  doSomethingWith(it.next(), i);
 }
bruno conde
+2  A: 

One of the changes Sun is considering for Java7 is to provide access to the inner Iterator in foreach loops. the syntax will be something like this (if this is accepted):

for (String str : list : it) {
  if (str.length() > 100) {
    it.remove();
  }
}

This is syntactic sugar, but apparently a lot of requests were made for this feature. But until it is approved, you'll have to count the iterations yourself, or use a regular for loop with an Iterator.

Yuval =8-)

Yuval
+2  A: 

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++); }
                    ...
                }
            }
        }
    }
}
Adrian
+1  A: 

http://zongmusic.wordpress.com/2010/03/26/java-tip-1-foreach-with-index/

Andi
Looks interesting. I'll have a closer look on that :)
Kosi2801
A: 

There is a "variant" to pax' answer... ;-)

int i = -1;
for(String s : stringArray) {
    doSomethingWith(s, ++i);
}
Jörg