How Does the Enhanced for Statement Work for Arrays, and How to Get an Iterator for an Array

How does the enhanced for statement work for arrays, and how to get an iterator for an array?

If you want an Iterator over an array, you could use one of the direct implementations out there instead of wrapping the array in a List. For example:

Apache Commons Collections ArrayIterator

Or, this one, if you'd like to use generics:

com.Ostermiller.util.ArrayIterator

Note that if you want to have an Iterator over primitive types, you can't, because a primitive type can't be a generic parameter. E.g., if you want an Iterator<int>, you have to use an Iterator<Integer> instead, which will result in a lot of autoboxing and -unboxing if that's backed by an int[].

Enhanced for loop with array

From the Java tutorial on this subject:

The for-each construct is also applicable to arrays, where it hides
the index variable rather than the iterator. The following method
returns the sum of the values in an int array:

// Returns the sum of the elements of a
int sum(int[] a) {
int result = 0;
for (int i : a)
result += i;
return result;
}

And from §14.14.2 of the JLS (the Java Language Specification):

The enhanced for statement has the form:

EnhancedForStatement:
for ( FormalParameter : Expression ) Statement

The type of the Expression must be Iterable or an array type, or a
compile-time error occurs.

But note that arrays don't implement Iterable; from §10.1 of the JLS:

The direct superclass of an array type is Object.

Every array type implements the interfaces Cloneable and java.io.Serializable.

Enhanced for-loop does not accept Iterator

The enhanced for loop was part of JSR 201. From that page, you can download the proposed final draft documents, which include a FAQ section directly addressing your question:

Appendix I. Design FAQ

  1. Why can't I use the enhanced for statement with an Iterator (rather
    than an Iterable or array)?

Two reasons: (1) The construct would not
provide much in the way on syntactic improvement if you had an
explicit iterator in your code, and (2) Execution of the loop would
have the "side effect" of advancing (and typically exhausting) the
iterator. In other words, the enhanced for statement provides a
simple, elegant, solution for the common case of iterating over a
collection or array, and does not attempt to address more complicated
cases, which are better addressed with the traditional for statement.


  1. Why can't I use the enhanced for statement to:

    • remove elements as I traverse a collection ("filtering")?
    • simultaneously iterate over multiple collections or arrays?
    • modify the current slot in an array or list?

See Item 1 above. The expert group considered these cases, but
opted for a simple, clean extension that dose(sic) one thing well. The
design obeys the "80-20 rule" (it handles 80% of the cases with 20% of
the effort). If a case falls into the other 20%, you can always use an
explicit iterator or index as you've done in the past.

In other words, the committee chose to limit the scope of the proposal, and some features that one could imagine being part of the proposal didn't make the cut.

Fastest way to iterate an Array in Java: loop variable vs enhanced for statement

If you're looping through an array, it shouldn't matter - the enhanced for loop uses array accesses anyway.

For example, consider this code:

public static void main(String[] args)
{
for (String x : args)
{
System.out.println(x);
}
}

When decompiled with javap -c Test we get (for the main method):

public static void main(java.lang.String[]);
Code:
0: aload_0
1: astore_1
2: aload_1
3: arraylength
4: istore_2
5: iconst_0
6: istore_3
7: iload_3
8: iload_2
9: if_icmpge 31
12: aload_1
13: iload_3
14: aaload
15: astore 4
17: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
20: aload 4
22: invokevirtual #3; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
25: iinc 3, 1
28: goto 7
31: return

Now change it to use an explicit array access:

public static void main(String[] args)
{
for (int i = 0; i < args.length; i++)
{
System.out.println(args[i]);
}
}

This decompiles to:

public static void main(java.lang.String[]);
Code:
0: iconst_0
1: istore_1
2: iload_1
3: aload_0
4: arraylength
5: if_icmpge 23
8: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
11: aload_0
12: iload_1
13: aaload
14: invokevirtual #3; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
17: iinc 1, 1
20: goto 2
23: return

There's a bit more setup code in the enhanced for loop, but they're basically doing the same thing. No iterators are involved. Furthermore, I'd expect them to get JITted to even more similar code.

Suggestion: if you really think it might make a significant difference (which it would only ever do if the body of the loop is absolutely miniscule) then you should benchmark it with your real application. That's the only situation which matters.

In a java enhanced for loop, is it safe to assume the expression to be looped over will be evaluated only once?

About the enhanced for statement, the Java Language Specifications writes:

The enhanced for statement has the
form:

EnhancedForStatement:
for ( VariableModifiersopt Type Identifier: Expression) Statement

The Expression must either have type
Iterable or else it must be of an
array type (§10.1), or a compile-time
error occurs.

The scope of a local variable declared
in the FormalParameter part of an
enhanced for statement (§14.14) is
the contained Statement

The meaning of the enhanced for
statement is given by translation into
a basic for statement.

If the type of Expression is a
subtype of Iterable, then let I be
the type of the expression
Expression.iterator(). The enhanced for statement is equivalent
to a basic for statement of the
form:

for (I #i = Expression.iterator(); #i.hasNext(); ) {

VariableModifiersopt Type Identifier = #i.next();
Statement
}

Where #i is a compiler-generated
identifier that is distinct from any
other identifiers (compiler-generated
or otherwise) that are in scope (§6.3)
at the point where the enhanced for
statement occurs.

Otherwise, the Expression necessarily
has an array type, T[]. Let L1 ... Lm
be the (possibly empty) sequence of
labels immediately preceding the
enhanced for statement. Then the
meaning of the enhanced for statement
is given by the following basic for
statement:

T[] a = Expression;
L1: L2: ... Lm:
for (int i = 0; i < a.length; i++) {
VariableModifiersopt Type Identifier = a[i];
Statement
}

Where a and i are compiler-generated
identifiers that are distinct from any
other identifiers (compiler-generated
or otherwise) that are in scope at the
point where the enhanced for statement
occurs.

So in your case, genArray() doesn't return a subtype of Iterable but an array type, so your enhanced for statement is equivalent to the following basic for statement:

String[] a = genArray();
...
for (int i = 0; i < a.length; i++) {
String s = a[i];
// ...
}

And genArray() will thus be called only once (but the currently accepted answer is partially wrong).

Enhanced For Loop - Array of Objects

Just use it in the for each

for(Dog d : kennel) {
d.bark();
}

Does JVM create an iterator when it iterates over array with for-each loop?

Arrays in Java don't implement Iterable interface so you cannot get an iterator from an array. Also you cannot have an Iterator over primitive types such as int because a primitive type can't be a generic parameter. E.g. if you want an Iterator, you have to use an Iterator instead, which will result in a lot of autoboxing and -unboxing if that's backed by an int[].

The JVM is unlikely to create iterator for for-each loop over arrays as it would be very inefficient.

In fact the compiler will transform the for-each loop into indexed for loop. You can check it by viewing the decompiled byte code for this method:

Source code:

public void test() {
int[] array = new int[20];
for (int el : array) {
System.out.println("test");
}
}

Decompiled byte-code:

public void test() {
int[] array = new int[20];
int[] var2 = array;
int var3 = array.length;

for(int var4 = 0; var4 < var3; ++var4) {
int var10000 = var2[var4];
System.out.println("lol");
}

}

What's happening under the hood of an enhanced for loop?

The enhanced for loop is covered by the JLS, Section 14.14.2:

  • For Iterable objects:

The enhanced for statement is equivalent to a basic for statement of the form:

for (I #i = Expression.iterator(); #i.hasNext(); ) {
{VariableModifier} TargetType Identifier =
(TargetType) #i.next();
Statement
}
  • For arrays:

The enhanced for statement is equivalent to a basic for statement of the form:

T[] #a = Expression;
L1: L2: ... Lm:
for (int #i = 0; #i < #a.length; #i++) {
{VariableModifier} TargetType Identifier = #a[#i];
Statement
}

It creates a new reference to the array, separate from your original reference. You can modify the reference to the array all you want, but it will still keep iterating over this implicit reference to the original array.

Over Iterables, only the reference to the Iterator is kept, which still refers back to the original Iterable object, even if you reassign the original variable during the loop.

Whether you use an enhanced for loop over an array or an Iterable, you can reassign the reference used as the target without affecting the result of the iteration -- you will still iterate over the original object referred by the target reference.

How is 'for each' looping construct applicable on arrays?

As far as I know for-each construct like for(String s : strArray) uses an Iterator internally to iterate over the elements.

Well it does when strArray is an iterable - it just works differently for arrays.

All the details are in section 14.14.2 of the JLS. In particular:

Otherwise, the Expression necessarily has an array type, T[].

Let L1 ... Lm be the (possibly empty) sequence of labels immediately preceding the enhanced for statement.

The enhanced for statement is equivalent to a basic for statement of the form:

T[] #a = Expression;
L1: L2: ... Lm:
for (int #i = 0; #i < #a.length; #i++) {
VariableModifiersopt TargetType Identifier = #a[#i];
Statement
}

#a and #i are automatically generated identifiers that are distinct from any other identifiers (automatically generated or otherwise) that are in scope at the point where the enhanced for statement occurs.

TargetType is the type of the loop variable as denoted by the Type that appears in the FormalParameter followed by any bracket pairs that follow the Identifier in the FormalParameter (§10.2).

In other words - when you're iterating over an array, it just uses the length field as if you wrote it out by hand.



Related Topics



Leave a reply



Submit