Array Details and Advanced Concepts
A for-each loop is an alternative form of the for loop that makes it easier to visit every value in an array or collection.
Predicting a Loop Before Running It
Programs often need to do the same thing to every item in a collection. Suppose you have an array of names and want to print each one. Before reading any explanation, try to predict what this loop prints, and in what order.
Ada
Grace
LinusWhat do you think happens?
Before running it, what appears on the screen and in what order?
Reveal answer
Ada, Grace, Linus, each on its own line, in that order
The loop visits the array from its first stored value to its last. Each pass makes the variable name hold one stored String, and the body prints that String. The loop does not print positions.
Tracing the Loop One Value at a Time
A for-each loop works as a cycle. Each trip around the cycle makes the loop variable hold a new value from the array, and the body runs with that value. The loop checks on each trip whether values remain. It does not check whether a counter has reached a particular number.
Trace the example one pass at a time. On pass one, name holds Ada and the body prints Ada. On pass two, name holds Grace and the body prints Grace. On pass three, name holds Linus and the body prints Linus. When no values remain, the loop stops. The printed output is therefore exactly the three stored values, in stored order.
Reading the For-Each Header
The general form of a for-each loop is a type, then a variable name, then a colon, then the array or collection to be walked through. The body in curly braces repeats once for each element. In the example above, the type is String, the variable is name, and the array is namelist.
for (Type variable : array) reads as: for each value of type Type, called variable, in the array, do the following. The colon is read as the word in or from.
- 1The type after the opening parenthesis, String, states the kind of value each pass will provide.
- 2The variable after the type, name, is the new name that holds one value on each pass.
- 3The colon separates the variable from the collection, and reads as in or from.
- 4The array after the colon, namelist, is the thing being traversed.
- 5The body in curly braces runs once for each value the loop provides.
Read aloud, the header in the example says: for each String, called name, in the array namelist, do the following. Read this way, the header describes a traversal. The loop visits the array in turn, and at each visit a single value is made available under the name you chose.
How the Loop Reaches Each Element
The most important fact about a for-each loop is that no array index appears in it. The loop control variable represents one of the values in the array. It does not represent that value's position. This is the sharpest contrast with the traditional for loop, which usually keeps an integer counter and uses that counter to fetch each element.
Use the traditional for loop when your code needs position information, such as printing the index beside each name or comparing neighboring elements. Use the for-each loop when you only need each value in turn.
Array Positions and the Values They Hold
An array stores its values in ordered positions. In the example, namelist has three stored values. A traditional loop reaches each value by asking for the value at a position. A for-each loop does not ask for positions at all, but the values are still visited in the same stored order.
Writing the Same Loop Both Ways
The following two programs print the same array. The for-each version needs only the header and the body. The traditional version must declare a counter, state where it starts, state when it stops, and fetch each element by its position.
Ada
Grace
Linus- No counter is declared.
- The variable name receives each value directly.
Ada
Grace
Linus- The counter i starts at 0.
- The loop continues while i is less than the array length.
- namelist[i] fetches each element by its position.
Choosing between the two forms
You need to print each name in namelist, and also print each name's position beside it.
- 1Check whether position is needed
The task asks for positions, and a for-each loop does not expose them.
- 2Choose the traditional form
The counter i gives the position, so the traditional for loop fits this task.
- 3Print both values
Inside the body, print i together with namelist[i] on each pass.
The traditional for loop is the right choice, because the position must be available inside the body.
Finding Where Output Diverges
When a for-each loop's output differs from what you expected, the problem is usually in one of three places: the header, the body, or the data in the array. Check them in that order, because the loop faithfully reports whatever the array holds.
Suppose the header is written as for (int name : namelist) instead of for (String name : namelist). The type after the opening parenthesis does not match the String values stored in namelist. Checking the header first reveals the mismatch immediately, before any output is examined.
- 1Check the header. Confirm that the type after the opening parenthesis matches the element type of the array, and that the array after the colon is the one you meant to traverse.
- 2Check the body. It runs once per value, so confirm that what it does is correct for a single value.
- 3Check the array contents. Confirm that the stored values are the ones you expected, because the loop reports them faithfully.
Mistakes Beginners Make with For-Each Loops
Common mistake Expecting an index variable inside a for-each loop
What it looks likefor (String name : namelist) { System.out.println(namelist[name]); }Why it failsThe loop variable holds a value, not a position, so it cannot be used to fetch an element by position.
Do this insteadPrint name directly, or use a traditional for loop with an integer counter if you need positions.
Common mistake Assuming the loop variable is a number
What it looks likefor (String name : namelist) { ... } is read as name counting from 0.Why it failsThe header says each pass receives one value from the array, not a counter.
Do this insteadRead the header as for each String, called name, in namelist.
Common mistake Writing a header whose type does not match the array
Why it failsThe type after the opening parenthesis must match the element type of the array.
Do this insteadMatch the type to the array's element type, such as String for an array of Strings.
Common mistake Blaming the loop when the array holds unexpected values
Tracing and Predicting Your Own Loops
Given String[] fruits = {"Pear", "Plum"} and the loop for (String f : fruits) { System.out.println(f); }, write down the exact lines printed, in order. Then state the value that f holds on the second pass.
Hints
- Count how many values the array holds, then trace one pass at a time.
- The variable f holds a value from fruits on each pass, not a position.
A learner predicted that the loop for (String name : namelist) would print three lines, but the program printed the same name twice and then stopped. Name the three places to check, in order, and say which pass would be the first to differ from the prediction.
Hints
- Start with the header, then the body, then the array contents.
- Identify the first pass whose printed value differs from the prediction.
Key Takeaways
- A for-each loop reads as for each value of a type, called a name, in an array, and its body runs once per stored value.
- The loop variable holds one value on each pass, and no index appears in the loop, so position information is not available inside it.
- Use a traditional for loop with an integer counter when the code needs positions, and a for-each loop when it only needs each value in turn.
- When output diverges from the prediction, check the header, then the body, then the array contents, and locate the first pass that differs.