These are called for-each loops, and can be applied to both arrays and collections. Format:
for ([type] [var-name] : [array or iterable value]) {
...
}
To use a for-each loop, you only need to satisfy one of two conditions:
- The iteration value is an array, or
- the iteration value is an
Iterable
.
The biggest reason we do this is because List
isn't the only Iterable
that we can use in the loop, but it is the only one that can be indexed. This allows you to do generic iteration instead of locking yourself into a fixed, indexed list format.
For example, HashSet
is not ordered, but I can still iterate over it in a for-each loop:
HashSet<String> strs = new HashSet<String>();
for (String str : strs) { ... }
I can also have a method take an Iterable
instead of a List
:
public static void printStrings(Iterable<String> strs) {
for (String str : strs) {
System.out.println(str);
}
}
There is no way for me to iterate over it using an index without first copying it into something else, like an array or a List
.
Another important reason to use the for-each loop is that it compiles to using the Iterator
off the list (via Iterable.iterator()
), which allows for fail-fast iteration. This results in things like ConcurrentModificationException
s to tell us that the collection was modified while we were iterating over it. For example, this will always throw a ConcurrentModificationException
:
List<String> strs = ... ;
for (String str : strs) {
strs.remove(str);
}
But this won't:
List<String> strs = ... ;
for (int i = 0; i < strs.length(); i++) {
strs.remove(str);
}
This is good for multi-threaded applications because you're supposed to lock the list before you access it since most List
implementations aren't designed for thread-safety, and iteration is never thread-safe without external synchronization, both with indexing and with Iterator
. If one thread is iterating over it while another changes it, this can (not guaranteed, but can) throw a ConcurrentModificationException
, which tells you that the list isn't properly locked. The indexed for could never give you this kind of information. Instead, it will just exhibit strange behavior like skipping elements.