MT2 - 2D Arrays

What is a 2D array?

A regular array is a single row of values:

int[] numbers = {10, 20, 30, 40};

A 2D array is essentially an array of arrays. Think of it like a table with rows and columns.

In java:

int[][] numbers = {

{10, 20, 30, 40},

{50, 60, 70, 80},

{90, 100, 110, 120}

};

How do we access values?

This is the most important rule:

numbers[row][column]

First number = row

Second number = column

For example:

numbers[0][0] // 10

numbers[0][2] // 30

numbers[1][1] // 60

numbers[2][3] // 120

Remember: Java starts counting at zero for BOTH rows and columns.


How do .length values work

This is where people get tripped up.

numbers.length

Gives you the number of rows: 3

numbers[0].length

Gives you number of columns in row 0: 4


Creating an empty 2D array

You can also create one without putting values in it:

int[][] scores = new int[3][4];

This creates an array with 3 rows 4 columns


Nested Loops

Why do we need nested loops?

With a regular array, one loop is enough

int[] numbers = {10, 20, 30, 40};

for (int i = 0; i < numbers.length; i++) {

System.out.println(numbers[i]);

}

But a 2D array has multiple rows AND columns

We need:

  • An outer loop to move between rows.

  • An inner loop to move through the columns in each row.

That's called a nested loop: a loop inside another loop.

The basic structure

for (int i = 0; i < numbers.length; i++) {

    for (int j = 0; j < numbers[i].length; j++) {

        System.out.println(numbers[i][j]);

}

}

i represents the current row, j represents column in that row


What if we want to calculate the sum?

Same nested loops, we js add an accumulator

int sum = 0;

for (int i = 0; i < numbers.length; i++) {

    for (int j = 0; j < numbers[i].length; j++) {
        sum += numbers[i][j];

}

}

System.out.println(sum);

Output:

210


Filling a 2D array

So far, we've been reading values already inside an array. But what if we want Java to populate the array ourselves?

Consider:

int[][] numbers = new int[3][4];

This creates 3 rows and 4 columns, all initially filled with zeroes.

We can use nested loops to fill it:

for (int i = 0; i < numbers.length; i++) {

for (int j = 0; j < numbers[i].length; j++) {

numbers[i][j] = i + j;

}

}

What’s happening?

  • i tells us what row

  • j tells us which column

  • i + j determines value placed in that position

The resulting array:


Column 0

Column 1

Column 2

Column 3

Row 0

0

1

2

3

Row 1

1

2

3

4

Row 2

2

3

4

5

The important takeaway: You can use i and j to calculate what gets stored at every position.


Row Sums vs Column Sums

Imagine this array represents scores from 3 students across 4 exams:

int[][] scores = {

{80, 90, 70, 85},

{95, 75, 85, 90},

{60, 80, 90, 95}

};

Calculating row sums:

Suppose we want the total score for each student.

We need to:

  1. Choose a row.

  2. Go through every column in that row.

  3. Add the values

Here’s how that looks like:

for (int i = 0; i < scores.length; i++) {

    int sum = 0

    for (int j = 0; j < scores[i].length; j++) {

        sum += scores[i][j];

}

System.out.println(sum);

}

Output:

325

345

325

Notice where int sum = 0 is located.

It’s inside the outer loop

Why? Because we want to reset the sum for every new student. Otherwise, we'd keep adding to the previous student's total.

Calculating column sums

Now let's calculate the total score for each exam.

This time, we reverse the order of our loops.

for (int j = 0; j < scores[0].length; j++) {

int sum = 0;

for (int i = 0; i < scores.length; i++) {

sum += scores[i][j];

}

System.out.println(sum);

}

Output:

235

245

245

270

The trick to remember:

  • Rows: outer loop goes through rows.

  • Columns: outer loop goes through columns.


Calculating Averages

Once you know how to calculate sums, averages are easy.

Average = Sum / Number of Values

For each student’s average:

double average = (double) sum / scores[i].length;

For each exam’s average:

double average = (double) sum / scores.length;

Why are the denominators different?

  • A row has as many values as there are columns

  • A column has as many values as there are rows


Finding row or column with highest sum

What’s the goal?

Suppose we have:

int[][] scores = {

{10, 20, 30},

{40, 50, 60},

{70, 80, 90}

};

We want to find which row has the highest total.

First, calculate each row:

Row

Calculation

Sum

0

10 + 20 + 30

60

1

40 + 50 + 60

150

2

70 + 80 + 90

240

So row 2 wins, with 240.

How do we make java find it?

First we need two variables:

int maxSum = Integer.MIN_VALUE;

int maxRow = -1;

  • maxSum stores the highest sum we've found so far.

  • maxRow remembers which row produced that sum.

  • Integer.MIN_VALUE starts us at the smallest possible integer, so even negative row sums work.


Now the loop:

for (int i = 0; int < scores.length; i++) {

    int sum = 0

    for (int j = 0; int < scores[i].length; j++; {

        sum += scores[i][j];

    }

    if (sum > maxSum) {

    maxSum = sum;

    maxRow = i;

    }

}

Let’s understand the logic:

Step 1: Calculate current row’s sum

Step 2: Compare it with highest sum we’ve seen

Step 3: If the current sum is bigger, update both variables.

That's it. We repeat for every row.

At the end:

System.out.println(maxRow);

System.out.println(maxSum);

Output:

2

240


What if we want the highest column sum?

Same exact idea but switch the loops around

int maxSum = Integer.MIN_VALUE;

int maxColumn = -1;

for (int j = 0; j < scores[0].length; j++) {

int sum = 0;

for (int i = 0; i < scores.length; i++) {

sum += scores[i][j];

}

if (sum > maxSum) {

maxSum = sum;

maxColumn = j;

}

}


Ragged Arrays

What is a ragged array?

So far, all our 2D arrays have been rectangular: every row has the same number of columns.

But Java allows rows to have different lengths.

That's called a ragged array.

Example:

int[][] numbers = {

{10, 20, 30},

{40, 50},

{60, 70, 80, 90}

};

Notice:

  • Row 0 has 3 elements.

  • Row 1 has 2 elements.

  • Row 2 has 4 elements.


How does .length work now?

numbers.length // 3

numbers[0].length // 3

numbers[1].length // 2

numbers[2].length // 4

The first .length tells us how many rows

Second .length tells us how many columns in the rows


Why does this matter for loops?

For regular rectangular arrays, you might see:

for (int i = 0; i < numbers.length; i++) {

for (int j = 0; j < numbers[0].length; j++) {

System.out.println(numbers[i][j]);

}

}

But with ragged arrays this could cause an error.

Why?

Because numbers[0].length is 3. When the loop reaches row 2, that row has 4 elements, so the fourth element never gets visited.

And if a row is shorter than row 0, accessing a nonexistent position can cause an error.

The safer approach is:

for (int i = 0; i < numbers.length; i++) {

    for (int j = 0; j < numbers[i].length; j++) {

        System.out.println(numbers[i][j]);

}

}

Always use numbers[i].length when looping through each row.