Logout

(Loops Within Loops &) 2D Arrays

Here's the link to the first spiral of arrays notes. What is here follows on from that.

But a vvvvvery quick summary would be the following:

int [] myIntArray = new int[3];

which makes an 32-bit object/reference variable called myIntArray which points to three contiguous 32-bit groups in memory which will be three ints. So then, we could go:

myIntArray[0] = 23;
myIntArray[1] = 88;
myIntArray[2] = 99;

which assigns those values to the three elements of the array.

The "Old Fashioned" Braces Way of Declaring Arrays

To better appreciate two dimentional arrays, it will be helpful to look at another way of explicitly declaring them. Here's that way that works, for a single dimension array, using the same one as above.

int [] myIntArray = { 23, 88, 99 };

So the declaration and the assignment all happen in the same line. There is no need to have a part of the declaration which stipulates the number of elements and reserves memory with the new operator, since the elements are all assigned right within the line.
At this point it will be good to note that the length of this array is 3, and we get that value with: myIntArray.length


So what about a 2D array declared this old fashioned braces way?

In fact, a 2D array is an array of arrays, so the braces way of declaring it would be as follows:

int [][] myIntArray = { { 23, 88, 99 } , { 55, 23, 46 } , { 36, 40, 73} , { 54, 93, 10 } };

Above, you have an array of four arrays; each one of those "sub"-arrays is three ints.
Do note that declaring it as 2D, we need to have two pairs of array declaration braces: [][]

So what about the length of the above array? Well it itself is 4; it is an array of 4 sub-arrays, so its length is 4. We just use the length attribute as usual, as follows:

myIntArray.length

But when it comes time to loop through the entire array, we are going to want to know how many times to loop within each sub-array, so we'll want the sub-array's lengths too. Since the sub-arrays are indeed arrays, we can use the .length attribute for them too, but how to access that? Well, we take any one of the sub arrays, and get its .length attribute. To do that, we can use any of the sub-arrays, the [0]th, or the [1]st, or the [2]nd, or the [3]rd, it doesn't matter, since they are all the same length - 3. Here is the line for doing this:

myIntArray[0].length

(Usually we just use the [0]th, since all arrays, even one with only one element, will have a [0]th element.)


"Loop Within Loop" - Nested Loops

Before going further, since in order to access all the elements of a 2D array, we will be looping through arrays, which themselves will have to be looped through, we should look in a bit of deatail at loops within loops, i.e. nested loops. The whole idea is that the inner loop will fully loop within each loop of the outer loop. (Repeat that last sentence a couple of times to yourself until it makes sense, and you've got the idea.) Consider the following:

LooopsWithinLooops.java
/Users/adelaide/Public/Netbeans - All JSR Projects/ArraysSecondSpiral/src/arraysspiral2/LooopsWithinLooops.java
        for (int i = 0; i < 6; i++) {
            for (int k = 0; k < 4; k++) {
                    System.out.print(k);
            }System.out.println();
        }

The output would be:

0123
0123
0123
0123
0123
0123

Note that 0 1 2 and 3 go on the same line, since they are output with print(), rather than println().

And the line by line trace of i and k would be:

i: 0
k: 0
sout k, so 0
k: 1
sout k on the same line, so 01
k: 2
sout k on the same line, so 012
k: 3
sout k on the same line, so 0123
now k goes ++ to 4, and k < 4 is no longer true, so exit the inner loop
sout to a new line

i++ to i: 1
k: 0
sout k, so 0
k: 1
sout k on the same line, so 01
k: 2
sout k on the same line, so 012
k: 3
sout k on the same line, so 0123
now k goes ++ to 4, and k < 4 is no longer true, so exit the inner loop
sout to a new line

i++ to i: 2
k: 0
sout k, so 0
k: 1
sout k on the same line, so 01
k: 2
sout k on the same line, so 012
k: 3
sout k on the same line, so 0123
now k goes ++ to 4, and k < 4 is no longer true, so exit the inner loop
sout to a new line

i++ to i: 3
k: 0
sout k, so 0
k: 1
sout k on the same line, so 01
k: 2
sout k on the same line, so 012
k: 3
sout k on the same line, so 0123
now k goes ++ to 4, and k < 4 is no longer true, so exit the inner loop
sout to a new line

i++ to i: 4
k: 0
sout k, so 0
k: 1
sout k on the same line, so 01
k: 2
sout k on the same line, so 012
k: 3
sout k on the same line, so 0123
now k goes ++ to 4, and k < 4 is no longer true, so exit the inner loop
sout to a new line

i++ to i: 5
k: 0
sout k, so 0
k: 1
sout k on the same line, so 01
k: 2
sout k on the same line, so 012
k: 3
sout k on the same line, so 0123
now k goes ++ to 4, and k < 4 is no longer true, so exit the inner loop

i ++ to 6, and so i < 6 is no longer true, so exit the outer loop

 

Looping Throgh a 2D Array

So... how do we loop through a 2D array? Well it's a loop within a loop, where the outer loop is controlled by the number of sub-arrays, and the inner loop is controlled by the number of elements in the sub-arrays. First, here's the code:

LooopsWithinLooops.java
/Users/adelaide/Public/Netbeans - All JSR Projects/ArraysSecondSpiral/src/arraysspiral2/LooopsWithinLooops.java
int [][] twoDArray = { { 55, 56, 57, 58 }, {22, 23, 24, 25} , {36, 37, 38, 39} };

for(int row = 0; row < twoDArray.length ; row++){
      for(int col = 0; col < twoDArray[0].length; col++){
          System.out.println(twoDArray[row][col]);
      }
      System.out.println(""); 
}

Note the convention to name the loop control variables row and col, since this is what they represent if we are to think of our 2D array as a table.

By using .length for the one dimension, and [0].length for the other dimension, we can loop through the whole two dimensional structure, one element at at time.

The Output:

55 56 57 58
22 23 24 25
36 37 38 39

And the line by line trace of row and col would be:

row: 0
col: 0
sout [row][col], so [0][0], so 55
col: 1
sout [row][col], so [0][1], so 55 56
col: 2
sout [row][col], so [0][2], so 55 56 57
col: 3
sout [row][col], so [0][3], so 55 56 57 58
now col goes ++ to 4, and col < twoDArray[0].length, is no longer true, so exit the inner loop
sout to a new line

row++ to row: 1
col: 0
sout [row][col], so [1][0], so 22
col: 1
sout [row][col], so [1][1], so 22 23
col: 2
sout [row][col], so [1][2], so 22 23 24
col: 3
sout [row][col], so [1][3], so 22 23 24 25
now col goes ++ to 4, and col < twoDArray[0].length, is no longer true, so exit the inner loop
sout to a new line

row++ to row: 2
col: 0
sout [row][col], so [2][0], so 36
col: 1
sout [row][col], so [2][1], so 36 37
col: 2
sout [row][col], so [2][2], so 36 37 38
col: 3
sout [row][col], so [2][3], so 36 37 38 39
now col goes ++ to 4, and col < twoDArray[0].length, is no longer true, so exit the inner loop
sout to a new line

row++ to row: 3, and row < twoDArray.length is no longer true, so exit the outer loop

The Non-braces Way to Declare & Loop Through 2D Arrays

Declaring:

We declare a 2d array the same way as a single-dimension array, except that there are two dimensions, so two [] on either side of the assignment operator:

Example 1, an array to keep track of 10 row and 5 columns of random ints:

int [][] my2DArray = new int [10][5];

or

Example 2, an array of 70 groups of related String pairs:

String [][] s = new String [70][2];

Assigning:

To assign data to 2d arrays, there are generally two approaches:
- most often we use the same loop within loop process as seen above, with the outer loop the rows, and so often using "row" as the loop control variable, and the inner loop being the columns, and so often using "col" as that loop control variable.

for(int i = 0; i < my2DArray.length; i++){
      for(int k = 0; k < my2DArray[0].length; i++){
            my2DArray[i][k] = (int) (Math.random()*60);
      }
}


But often there is another approach, which would probably be used for the second example above. In this case, we don't loop through the items in each row with a for loop, rather, we just directly assign to the [0]th element, and then the [1]st element directly, with individual lines, over and over again. Though this isn't "looping" in the traditional for loop sense, it still accomplishes looping per se.

This way of doing things is often done in our GUI code workig with tables.

for(int row = 0; row < s.length; s++){
      System.out.println("What is the next student name you wish to enter?");
      s[row][0] = br.readLine();
      System.out.println("What is the address of this student?);
      s[row][1] = br.readLine();
}