CS 4: Lecture 10 Wednesday, February 22, 2006 "for" Loops ----------- "for" loops are a convenient shorthand that can be used to write some "while" loops in a more compact way. The following "for" loop is equivalent to the following "while" loop. for (initialize; condition; next) { | initialize; statements; | while (condition) { } | statements; | next; | } "for" statements are usually used to iterate while advancing an index variable over a fixed range of values. The following code repeats a statement 100 times. int i; for (i = 0; i < 100; i++) { System.out.println("I will not make Java serve detention for me."); } // Loop body ends at this "}". A common mistake among beginning Java and C programmers is to get the conditional wrong and do one loop iteration too few. For example, suppose you want to print all the prime numbers in the range 2...n. for (int i = 2; i < n; i++) { // ERROR!!! Condition should be i <= n. if (isPrime(i)) { System.out.print(i + "is prime."); } } Suppose we correct this method so the loop test is "i <= n". Think carefully: what is the value of i when the loop ends? MORE ARRAYS =========== When you construct an array, Java automatically initializes all its values to zero (or false for an array of booleans). double[] miles = new double[4]; --- ------------------------- miles |.+----->| 0.0 | 0.0 | 0.0 | 0.0 | --- ------------------------- You can declare an array of objects--but it's really an array of references. Java initializes these references to a value of "null", which means that they don't point to anything. You can set them to point to objects, but they all have to be of the class you used in the definition. String[] sentence = new String[3]; sentence[0] = "Word"; sentence[2] = new String(); --- -------------------- --- sentence |.+----->| . | null | .--+---->| | --- ---+---------------- --- empty String | | -------- \---->| Word | -------- You can use fields or methods on objects in an array by combining the array notation with the dot notation. sentence[1] = sentence[0].concat(sentence[0]); main()'s Parameter ------------------ What is the array of Strings that the main() method takes as a parameter? It's a list of command-line arguments sent to your Java program. In Gild, you can supply these through a menu item. If you have a command-line Java (most common in Unix), you type them on the command line. Consider the following program. class Echo { public static void main(String[] args) { for (int i = 0; i < args.length; i++) { System.out.println(args[i]); } } } If we compile this and type "java Echo kneel and worship Java" on a Unix command line, java prints kneel and worship Java Multi-Dimensional Arrays ------------------------ A _two-dimensional_array_ is an array of references to arrays. Java can construct an array of arrays for you with one command. Let's construct a multiplication table. long[][] table; // table's type is "array of arrays of longs". table = new long[x][y]; // Construct an array of x arrays of y longs each. for (int i = 0; i < x; i++) { for (int j = 0; j < y; j++) { table[i][j] = i * j; } } The array objects look like this: ----------------------------- ------------------------------->| 0 | 0 | 0 | 0 | 0 | | ----------------------------- | ----------------------------- | ------------------------->| 0 | 1 | 2 | 3 | 4 | | | ----------------------------- | | ----------------------------- | | ------------------->| 0 | 2 | 4 | 6 | 8 | | | | ----------------------------- | | | ----------------------------- | | | ------------->| 0 | 3 | 6 | 9 | 12 | | | | | ----------------------------- --- ---+-----+-----+-----+-------- ----------------------------- table |.+----->| . | . | . | . | .-+---->| 0 | 4 | 8 | 12 | 16 | --- ------------------------------ ----------------------------- It's important to understand the order of the array indices. Does table[i][j] mean we look up the jth element of the ith array, or vice versa? It might help you to keep in mind that you can address just one index at a time. long[] row = table[3]; Now "row" references an array of longs--the array stored at index "3" of the array of arrays. Then the following two lines access the same long. z = row[1]; z = table[3][1]; // Both lines access the same array element. Think of the dereferencing operation "[1]" as an operation on the array that precedes it, which in this case is "table[3]". You could even write z = (table[3])[1]; to remind yourself that we look up index 3 first, then index 1. This is perfectly valid Java code. You can also construct a three-dimensional array--an array of arrays of arrays--or a four-dimensional or whatever-dimensional array. long[][][][] tensor = new long[3][4][5][2]; But if you try to construct a high-dimensional array where each dimension of the array is large, you'll find you run out of memory pretty fast. A 100-by-100-by-100-by-100 array of longs takes about a gigabyte to store. It's convenient that Java will construct all the arrays for you, at every dimension. But arrays are the only class of object Java will do this for. If you construct an array of other types of objects, like Planet objects, Java will just construct an array of null references; you'll have to write a loop to construct the Planets themselves. Initializers ------------ When you declare a variable that references an array, you can also construct arrays and initialize array entries by using _initializers_. long[] a = {7, 12, 5, -3}; String[] b = {"milk", "fish", new String()}; int[][] c = {{7, 3, 2}, {x}, {8, 5, 0, 0}, {y + z, 3}}; The third line constructs a two-dimensional array: ------------------- ------------------------->| 7 | 3 | 2 | | ------------------- | ------- | ------------------->| 9 | | | ------- | | ------------------------- | | ------------->| 8 | 5 | 0 | 0 | | | | ------------------------- --- ----+-----+-----+-------- ------------- c |.+-----> | . | . | . | .-+---->| 6 | 3 | --- ------------------------- ------------- Observe here that two-dimensional arrays don't have to be rectangular--each array can be a different length. Alas, you can only use initializer notation in a declaration. Java will proclaim a compiler error if you try to write d = {3, 7}; f({1, 2, 3}); How could you loop through an array like "c" above? Since each row has a different length, you need to write a loop that looks up each row's length. Let's look at a nested loop that prints out an array as a String. public static String arrayToString(int[][] array) { String out = "[ "; for (int i = 0; i < array.length; i++) { out = out + "[ "; for (int j = 0; j < array[i].length; j++) { out = out + array[i][j] + " "; } out = out + "] "; } return out + "]"; } System.out.println(arrayToString(c)); This code prints the array like this: [ [ 7 3 2 ] [ 9 ] [ 8 5 0 0 ] [ 6 3 ] ]