Lecture 6: Nested loops and 2D arrays

Objectives

  • Read and write nested loops
  • Understand two dimensional arrays
  • Be able to use a nested loop to traverse a 2D array

What are some use cases for 2D arrays and nested loops?

  • Storing and processing images
  • Processing lists-of-lists, such as searching through an essay for keywords
  • Other examples?

Nested loops

Just like nesting if statements, you can also nest loops. We’ll start by writing code that, for a list of integers, produces all the possible pairs in that list. This is a common idiom: to use a nested for loop to iterate over a 1D array to generate all pairs.

public class NestedForLoopTemplate {
    public static void main(String args[]) {
        int[] list = {3, 4, 11, 2, 7, 5};
       
        for (int i = 0; i < list.length; i++){
            for (int j = 0; j < list.length; j++){
                System.out.print("possible pair(");
                System.out.print(list[i]);
                System.out.print(", ");
                System.out.print(list[j]);
                System.out.println(")");
            }
        }
    }
}  

Let’s trace through the code together using the visualizer. You’ll notice that even with such a short list, there are many possible pairs – the study of combinatorics is useful for reasoning about how to make strong passwords that are difficult for an automated system like this one to crack.

Note: we’ve used System.out.print (as opposed to println) to avoid printing each number on a single line.

Two dimensional arrays

We saw earlier that when we declare an array such as int[] array1 = {1, 2, 4}; the value stored in array1 on the stack is something like A100 (an arbitrary memory address on the heap – this is just our shorthand for memory addresses). The actual array of [1, 2, 4] lives in the heap at address A100.

What this means is that an array is stored as a memory address (i.e. A100), and there is no reason we can’t make an array of arrays:

public class Grid {
    public static void main(String args[]) {
       int[] row1 = {1, 2, 3, 4};
       int[] row2 = {5, 6};
       int[] row3 = {9, 10, 11, 12};
       int[][] grid = {row1, row2, row3};

       int[] newRow = {}; // empty array
       grid[2] = newRow;
       grid[1][0] = 11;

       boolean[][] empty = new boolean[3][4];
       int[][] small = {{1, 2, 3}, row2, {5, 6}};
    }
}

A 2D array is declared with double brackets [][], because it is an array of arrays. You should think of a 2D array as a grid, with a set of rows, where each row has cells (some number of columns). Note, like above, that a 2D array does not have to be a perfect rectangle; it can be ragged.

Class Participation Activity 1 [10 min]

Let’s trace through the code above on the board using the A100 notation to see how 2D arrays are represented in memory. This starts to illustrate why we store the actual contents of an array on the heap, and not the stack.

You can also plug this code into the visualizer, but note how messy it is to read without the A100-style addressing.

Conceptually, the syntax for 2D arrays is the same as for 1D arrays, just with another dimension.

Iterating over 2D arrays using nested for loops

Finally, we can use nested for loops to visit every element in a 2D array:

public class Grid{
    public static void main(String args[]){
        int[][] array = {{1, 2, 3}, {}, {5, 6}};
       
        for(int row = 0; row < array.length; row++){
            for(int col = 0; col < array[row].length; col++){
                System.out.println("cell: " + array[row][col]);
            }
        }
    }
}

Above, we name the loop iterators row and col for ease of understanding. Let’s watch how this behaves in the visualizer.

Class Participation Activity 2 [10 min]

Modify the code above so that it prints out the length of each row before printing out the elements on that row.

Modify the code above so that it prints out finished row when done with a row.

You now have another conceptual idiom for visiting every element in a 2D array using a nested for loop:

public class Grid {
    public static void main(String args[]) {
        int[][] array = {{1, 2, 3}, {}, {5, 6}};
       
        for(int row = 0; row < array.length; row++){
            System.out.println("start of row");
            for(int col = 0; col < array[row].length; col++){
                System.out.println("current tile: " + array[row][col]);
            }
            System.out.println("end of row");
        }
    }
}

Next class

We’ll start HW6 to get more practice with nested loops and 2D arrays.