The enhanced for loop is also called the for-each loop, and it offers some advantages over the regular for loop. It also has some limitations.
5.4.1 Iteration with enhanced for loop
To start with, the regular for loop is cumbersome to use when it comes to iterating through a collection or an array. You need to create a looping variable and specify the start and end positions of the collection or the array, even if you want to iterate through the complete collection or list. The enhanced for loop makes the previously mentioned routine task quite a breeze, as the following example demonstrates for the ArrayListmyList:
ArrayList<String> myList= new ArrayList<String>();
myList.add("Java");
myList.add("Loop");
Array declaration
b
Array allocation
c
Outer for loop
d
Inner for loop
e
Inner for loop ends Outer for loop ends
multiArr 0
0 1
0 1 2
0 1 2 1 2
1 2 3 Figure 5.14 The array multiArr after its initialization
[5.2] Create and use for loops including the enhanced for loop
353 The enhanced for loop
The following code uses the regular for loop to iterate through this list:
for(Iterator<String> i = myList.iterator(); i.hasNext();) System.out.println(i.next());
This code uses the enhanced for loop to iterate through the list myList:
for (String val : myList) System.out.println(val);
You can read the colon (:) in a for-each loop as “in.”
The for-each loop is a breeze to implement: there’s no code clutter, and the code is easy to write and comprehend. In the preceding example, the for-each loop is read as “for each element val in collection myList, print the value of val.”
You can also easily iterate through nested collections using the enhanced for loop.
In this example, assume that an ArrayList of exams, levels, and grades is defined as follows:
ArrayList<String> exams= new ArrayList<String>();
exams.add("Java");
exams.add("Oracle");
ArrayList<String> levels= new ArrayList<String>();
levels.add("Basic");
levels.add("Advanced");
ArrayList<String> grades= new ArrayList<String>();
grades.add("Pass");
grades.add("Fail");
The following code creates a nested ArrayList, nestedArrayList, every element of which is itself an ArrayList of String objects:
ArrayList<ArrayList<String>> nestedArrayList =
new ArrayList< ArrayList<String>>();
nestedArrayList.add(exams);
nestedArrayList.add(levels);
nestedArrayList.add(grades);
The nestedArrayList can be compared to a multidimensional array, as shown in fig- ure 5.15.
ArrayList of ArrayList
Add object of ArrayList to nestedArrayList
0 1 2
0 1
0 1
0 1 nestedArrayList
exams Java
Oracle
levels Basic
Advanced
grades Pass
Fail Figure 5.15 Pictorial representation of nestedArrayList
354 CHAPTER 5 Flow control
A nested enhanced for loop can be used to iterate through the nested ArrayList nestedArrayList. Here’s the relevant code:
for (ArrayList<String> nestedListElement : nestedArrayList) for (String element : nestedListElement)
System.out.println(element);
The output of this code is as follows:
Java Oracle Basic Advanced Pass Fail
The enhanced for loop is again a breeze to use to iterate through nested or non-nested arrays. For example, you can use the following code to iterate through an array of ele- ments and calculate its total:
int total = 0;
int primeNums[] = {2, 3, 7, 11};
for (int num : primeNums) total += num;
What happens when you try to modify the value of the loop variable in an enhanced for loop? The result depends on whether you’re iterating through a collection of primitive values or objects. If you’re iterating through an array of primitive values, manipulation of the loop variable will never change the value of the array being iterated because the primitive values are passed by value to the loop variable in an enhanced for loop.
When you iterate through a collection of objects, the value of the collection is passed by reference to the loop variable. Therefore, if the value of the loop variable is manipulated by executing methods on it, the modified value will be reflected in the collection of objects being iterated:
StringBuilder myArr[] = {
new StringBuilder("Java"), new StringBuilder("Loop") };
for (StringBuilder val : myArr) System.out.println(val);
for (StringBuilder val : myArr) val.append("Oracle");
for (StringBuilder val : myArr) System.out.println(val);
Iterates through array myArr and prints Java and Loop
Appends Oracle to value referenced by loop variable val Iterates through array myArr and prints JavaOracle and LoopOracle
355 The enhanced for loop
The output of the preceding code is
Java Loop JavaOracle LoopOracle
Let’s modify the preceding code. Instead of calling the method append on the loop variable val, let’s assign to it another StringBuilder object. In this case, the original elements of the array being iterated won’t be affected and will remain the same:
StringBuilder myArr[] = {
new StringBuilder("Java"), new StringBuilder("Loop") };
or (StringBuilder val : myArr) System.out.println (val);
for (StringBuilder val : myArr) val = new StringBuilder("Oracle");
for (StringBuilder val : myArr) System.out.println (val);
The output of the preceding code is
Java Loop Java Loop
EXAM TIP Watch out for code that uses an enhanced for loop and its loop variable to change the values of elements in the collection that it iterates. This behavior often serves as food for thought for the exam authors.
5.4.2 Limitations of the enhanced for loop
Although a for-each loop is a good choice for iterating through collections and arrays, it can’t be used in some places.
CAN’TBEUSEDTOINITIALIZEANARRAYANDMODIFYITSELEMENTS
Can you use an enhanced for loop in place of the regular for loop in the following code?
int[] myArray = new int[5];
for (int i=0; i<myArray.length; ++i) { myArray[i] = i;
if ((myArray[i]%2)==0)
myArray[i] = 20;
}
Iterates through array myArr and prints Java and Loop
Assigns new StringBuilder object to reference variable val with value Oracle Iterates through array myArray
and still prints Java and Loop
Declare
array count=length of the array Initialize array elements Modify array
elements
356 CHAPTER 5 Flow control
The simple answer is no. Although you can define a counter outside the enhanced for loop and use it to initialize and modify the array elements, this approach defeats the purpose of the for-each loop. The traditional for loop is easier to use in this case.
CAN’TBEUSEDTODELETEORREMOVETHEELEMENTSOFACOLLECTION
Because the for loop hides the iterator used to iterate through the elements of a col- lection, you can’t use it to remove or delete the existing collection values because you can’t call the remove method.
If you assign a null value to the loop variable, it won’t remove the element from a collection:
ArrayList<StringBuilder> myList= new ArrayList<>();
myList.add(new StringBuilder("One"));
myList.add(new StringBuilder("Two"));
for (StringBuilder val : myList) System.out.println (val);
for (StringBuilder val : myList) val = null;
for (StringBuilder val : myList) System.out.println(val);
The output of the preceding code is
One Two One Two
CAN’TBEUSEDTOITERATEOVERMULTIPLECOLLECTIONSORARRAYSINTHESAMELOOP
Although it’s perfectly fine for you to iterate through nested collections or arrays using a for loop, you can’t iterate over multiple collections or arrays in the same for- each loop because the for-each loop allows for the creation of only one looping vari- able. Unlike the regular for loop, you can’t define multiple looping variables in a for- each loop.
EXAM TIP Use the for-each loop to iterate over arrays and collections. Don’t use it to initialize, modify, or filter them.
5.4.3 Nested enhanced for loop
First of all, working with a nested collection is not the same as working with a nested loop. A nested loop can also work with unrelated collections.
As discussed in section 5.3.4, loops defined within another loop are called nested loops. The loop that defines another loop within itself is called the outer loop, and the loop that’s defined within another loop is called the inner loop. Theoretically, the level of nesting for any of the loops has no limits, including the enhanced for loop.
In this section, we’ll work with three nested, enhanced for loops. You can compare a three-level nested loop with a clock that has hour, minute, and second hands. The
Doesn’t remove an object from list; sets value of loop variable to null
357 The enhanced for loop
second hand of the clock completes a full circle each minute. Similarly, the minute hand completes a full circle each hour. This comparison is shown in figure 5.16.
The following is a coding example of the nested, enhanced for loop, which I dis- cussed in a previous section:
ArrayList<String> exams= new ArrayList<String>();
exams.add("Java"); exams.add("Oracle");
ArrayList<String> levels= new ArrayList<String>();
levels.add("Basic"); levels.add("Advanced");
ArrayList<String> grades= new ArrayList<String>();
grades.add("Pass"); grades.add("Fail");
for (String exam : exams) for (String level : levels) for (String grade : grades) System.out.println(exam+":"+level+":"+grade);
An inner loop in a nested loop executes for each iteration of its outer loop. The preced- ing example defines three enhanced for loops: the outermost loop at B, the inner nested loop at c, and the innermost loop at d. The complete innermost loop at d
executes for each iteration of its immediate outer loop defined at c. Similarly, the com- plete inner loop defined at c executes for each iteration of its immediate outer loop defined at B. Figure 5.17 shows the loop values for which all of these loops iterate.
Second hand (Innermost loop) Hour hand
(Outermost loop)
Minute hand (Inner loop)
1 hour = 60 minutes
1 hour = 1 complete revolution by minute hand 1 min = 60 seconds
1 min = 1 complete revolution by second hand
Figure 5.16 Comparison between a clock with three hands and the levels of a nested for loop
First ArrayList
Second ArrayList Third
Array- List
Outermost
b loop
Inner nested loop
c
Innermost nested loop
d
for (String exam : exams) for (String level : levels)
for (String grade : grades)
System.out.println(exam+":"+level+":"+grade);
Iterates forJava Oracle, Iterates forBasic Advanced, Iterates forPass Fail,
Figure 5.17 Nested for loop with the loop values for which each of these nested loops iterates
358 CHAPTER 5 Flow control
The output of the preceding code is as follows:
Java:Basic:Pass Java:Basic:Fail Java:Advanced:Pass Java:Advanced:Fail Oracle:Basic:Pass Oracle:Basic:Fail Oracle:Advanced:Pass Oracle:Advanced:Fail
EXAM TIP A nested loop executes all its iterations for each single iteration of its immediate outer loop.
Apart from the for loops, the other looping statements on the exam are while and do-while, which are discussed in the next section.