You can nest as many for
/while
loops as you'd practically want in Java: there's no practical limit.
Java has 4 looping constructs:
Java does not have goto
(which isn't really needed anyway).
See also
Examples
This is a typical example of a simple "triangle"-type nested loop, where the number of iteration of the inner loop depends on the value being iterated in the outer loop:
for (int i = 1; i <= 5; i++) { // prints:
for (int j = 0; j < i; j++) { // *
System.out.print("*"); // **
} // ***
System.out.println(); // ****
} // *****
Here's an example of a "pairing"-type nested loop, where the two loops are independent of each other, using the for-each construct:
int[] numbers = { 1, 2, 3 }; // prints: // if swapped:
char[] letters = { 'A', 'B', 'C' }; // 1 A // 1 A
// 1 B // 2 A
for (int number : numbers) { // 1 C // 3 A
for (char letter : letters) { // 2 A // 1 B
System.out.println(number + " " + letter); // 2 B // 2 B
} // 2 C // 3 B
} // 3 A // 1 C
// 3 B // 2 C
// 3 C // 3 C
The for-each
construct, which lacks explicit indices, makes the indepedence of both loops obvious: you can swap the two for
statements in the above code, and you'd still get all pairs, though listed in a different order.
This use of a boolean
method for a while
loop (this one from java.util.Scanner
) is typical:
Scanner sc = new Scanner("here we go again"); // prints:
while (sc.hasNext()) { // hereeeee
String s = sc.next(); // weeeee
char lastChar = s.charAt(s.length() - 1); // gooooo
for (int i = 0; i < 4; i++) { // againnnnn
s += lastChar;
}
System.out.println(s);
}
And here's an example that shows how do-while
is different from while-do
and for
:
int x = 0;
do {
System.out.println("Hello!!!");
} while (x != 0);
The above loop prints Hello!!!
: the body of a do-while
is executed before the termination condition is checked.
A more elaborate example
Here's an example of a nested-loop logic, but refactored into methods to make things more readable. This is something that is important for beginners to learn: just because you can physically nest loops as many levels as you want, doesn't mean you should. By breaking apart the logic like this, the program becomes more modular and readable, and each logic stands on its own and can be tested and reused, etc.
This snippet reverses the letters of a word in a char[]
in-place.
static void swap(char[] arr, int i, int j) {
char t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
static void reverse(char[] arr, int from, int to) {
int N = (to - from);
for (int i = 0; i < N / 2; i++) {
swap(arr, from+i, to-1-i);
}
}
public static void main(String[] args) {
char[] sentence = "reversing letters of words in sentence".toCharArray();
final int L = sentence.length;
int last = 0;
for (int i = 0; i <= L; i++) {
if ((i == L) || (sentence[i] == ' ')) {
reverse(sentence, last, i);
last = i + 1;
}
}
System.out.println(new String(sentence));
// prints "gnisrever srettel fo sdrow ni ecnetnes"
}
This example is also instructive in that even though it's essentially a nested loop algorithm, it's actually O(N)
! It's a mistake to think that any doubly nested-loop algorithm must be O(N^2)
-- it really depends on the algorithm itself more than just the physical structure.
Nested-loop Algorithms
These are classical algorithms traditionally implemented using nested loops (at least in their naive forms):
O(N^2)
Sorting algorithms:
O(N^3)
triply nested loop algorithms:
- Table-filling dynamic programming algorithms
These are far from an exhaustive sampling, but it should provide a good introduction to a variety of nested for
loops algorithms for beginners.