Java Multidimensional Arrays

In the last lesson you learned about Java traversing arrays. But a lot of real data is a grid, like a seating chart or a spreadsheet. For table-shaped data, Java gives you the two-dimensional array, often called a 2D array.

๐Ÿค” Why do we need 2D arrays?

A normal array is one row. A movie hall seat is not one number though. It is โ€œrow 2, seat 5โ€, two numbers. Chessboards and spreadsheets work the same way: each cell has a row and a column.

You could squeeze a table into a plain 1D array, but then you do index math by hand and bugs creep in. A 2D array is cleaner:

  • Say โ€œrow, then columnโ€ directly.
  • The data keeps its table shape, so the code reads like the problem.
  • No hand-done index math, so fewer mistakes.

The key idea: a 2D array is an array of arrays. Each item is a whole row. So you reach a value with two indexes, one for the row and one for the column.

The spreadsheet picture

Picture a spreadsheet. The rows go down. The columns go across. Cell B3 means column B, row 3. A 2D array is the same idea in code. You just use numbers for both, and both start at 0.

๐Ÿงฉ Creating a 2D array with known values

A 2D array type uses two pairs of square brackets: first index is the row, second is the column. When you know all the values, write them out directly. This is a matrix literal.

The code below builds a small grid of numbers right where it is declared.

int[][] grid = {
{1, 2, 3},
{4, 5, 6}
};

Reading it:

  • int[][] means โ€œan array of arrays of intโ€. Two brackets, two dimensions.
  • The outer { } holds the whole grid; each inner { } is one row.
  • So this grid has 2 rows and 3 columns.
  • grid[0] is the first row {1, 2, 3}; grid[1] is {4, 5, 6}. Each row is its own array.

This next snippet pulls out two single cells by their row and column.

System.out.println(grid[0][0]); // โœ… row 0, column 0
System.out.println(grid[1][2]); // โœ… row 1, column 2

Read grid[1][2] as โ€œrow 1, column 2โ€: row 1 is {4, 5, 6}, column 2 is 6. Both indexes start at 0, so the first cell is grid[0][0], not grid[1][1].

Output

1
6

๐Ÿ”ข Creating an empty grid with new

When you do not know the values yet (filling from input or a calculation later), create the grid by its size using new. You give the number of rows and columns.

The code below makes an empty 2-by-3 grid, then sets a few cells.

int[][] grid = new int[2][3]; // โœ… 2 rows, 3 columns, all start at 0
grid[0][0] = 10;
grid[0][1] = 20;
grid[1][2] = 30;
  • A fresh int grid starts full of the default value 0, so every cell is 0 until you change it.
  • Here we set three cells; the rest stay 0.
  • The brackets are the shape: new int[rows][cols].
  • This is the form you reach for most often, since grids are usually filled by loops or input.

Default values

A new number grid fills with 0. A boolean grid fills with false. An object grid like String[][] fills with null. So you never get random junk, just the typeโ€™s default.

๐Ÿ” Looping over a 2D array

To visit every cell, use a nested loop: the outer loop walks down the rows, and the inner loop walks across the columns of the current row.

The program below prints a grid row by row.

public class PrintGrid {
public static void main(String[] args) {
int[][] grid = {
{1, 2, 3},
{4, 5, 6}
};
for (int row = 0; row < grid.length; row++) { // each row
for (int col = 0; col < grid[row].length; col++) { // each column in that row
System.out.print(grid[row][col] + " ");
}
System.out.println(); // new line after each row
}
}
}

Reading it:

  • The outer loop runs over rows using grid.length (the row count).
  • The inner loop runs over columns using grid[row].length (that rowโ€™s column count).
  • print, not println, keeps a whole row on one line.
  • After the inner loop, println() drops to the next line, so each row sits on its own line.

Output

1 2 3
4 5 6

Watch the two lengths closely. This is where people slip.

Two lengths, two meanings

grid.length is the number of rows. grid[row].length is the number of columns in that row. They are different, so use the right one for each loop. The outer loop uses the first, the inner loop uses the second.

When you only need the values, not their positions, the for-each loop is shorter: it walks each row, then each value in that row.

The version below prints the same grid using for-each.

int[][] grid = {
{1, 2, 3},
{4, 5, 6}
};
for (int[] currentRow : grid) { // each row is an int[]
for (int value : currentRow) { // each value in that row
System.out.print(value + " ");
}
System.out.println();
}

The outer loop variable is int[], more proof each row is its own array. Use for-each for just the values; use the index version when you need to know where you are, like setting a cell.

๐ŸŽฎ A real example: a tic-tac-toe board

A 2D array is perfect for a game board. Letโ€™s set up a tic-tac-toe board with characters and print it.

The program below holds a 3-by-3 board of char values and prints it.

public class Board {
public static void main(String[] args) {
char[][] board = {
{'X', 'O', 'X'},
{'O', 'X', 'O'},
{'X', 'O', 'X'}
};
for (int row = 0; row < board.length; row++) {
for (int col = 0; col < board[row].length; col++) {
System.out.print(board[row][col] + " ");
}
System.out.println();
}
}
}

Same nested loop, same row-and-column idea. Only the type changed from int to char. This is how real grid programs, from games to spreadsheets, hold and show their data.

Output

X O X
O X O
X O X

๐Ÿงฎ A worked example: adding up a marks grid

Letโ€™s do something useful. Alex and Riya each took three subjects. We store marks in a grid, one student per row, one subject per column, then total each student.

The program below fills a marks grid, then sums each row.

public class MarksTotal {
public static void main(String[] args) {
int[][] marks = {
{80, 75, 90}, // Alex
{60, 95, 70} // Riya
};
String[] names = {"Alex", "Riya"};
for (int row = 0; row < marks.length; row++) {
int total = 0;
for (int col = 0; col < marks[row].length; col++) {
total = total + marks[row][col]; // add each subject
}
System.out.println(names[row] + " scored " + total);
}
}
}

Reading it:

  • The outer loop picks one student (one row).
  • total resets to 0 at the start of each row, so each student counts fresh.
  • The inner loop adds up that studentโ€™s three subject marks.
  • After the inner loop, we print the name and the total.

Alex gets 80 + 75 + 90 = 245. Riya gets 60 + 95 + 70 = 225.

Output

Alex scored 245
Riya scored 225

This pattern, an outer loop for groups and an inner loop for items, shows up everywhere: sum a matrix, find the highest mark, count passes and fails. The shape stays the same.

๐Ÿชœ Jagged arrays: rows of different lengths

Rows do not have to be the same length. Each row is its own array, so rows can have different lengths. A 2D array with uneven rows is a jagged array. Since it is an array of arrays, nobody forces the inner arrays to match in size.

The code below builds a triangle-shaped grid where each row is longer than the last.

int[][] jagged = {
{1},
{2, 3},
{4, 5, 6}
};

Row 0 has one value, row 1 has two, row 2 has three. You can also build one with new: give the row count, leave the column size empty, then make each row separately.

The next snippet creates three rows of different sizes by hand.

int[][] jagged = new int[3][]; // โœ… 3 rows, column sizes not decided yet
jagged[0] = new int[1]; // row 0 has 1 column
jagged[1] = new int[2]; // row 1 has 2 columns
jagged[2] = new int[3]; // row 2 has 3 columns

This is exactly why the inner loop uses grid[row].length, not grid.length. Each row may be a different size, so you ask each row for its own length. Assume every row is the same size, and the loop reads past the end of the short rows.

The program below prints the jagged grid safely.

public class Jagged {
public static void main(String[] args) {
int[][] jagged = {
{1},
{2, 3},
{4, 5, 6}
};
for (int row = 0; row < jagged.length; row++) {
for (int col = 0; col < jagged[row].length; col++) { // each row's own length
System.out.print(jagged[row][col] + " ");
}
System.out.println();
}
}
}

Because the inner loop asks each row for its length, every row prints correctly, short or long.

Output

1
2 3
4 5 6

๐ŸงŠ A quick word on 3D arrays

Two dimensions give a table; three give a stack of tables. A three-dimensional array uses three brackets, like int[][][]. Picture a building: floors, then rows, then columns. So cube[floor][row][col] reaches one cell.

The line below makes a 3D array and sets one cell.

int[][][] cube = new int[2][3][4]; // 2 floors, each 3 rows by 4 columns
cube[1][2][3] = 99; // floor 1, row 2, column 3

You loop over it with three nested loops, one per dimension. In real code you rarely go past two dimensions, since more get hard to picture. But the idea scales: add another bracket and another loop.

๐Ÿ“Š Rows and columns at a glance

The key pieces, kept straight.

Quick reference

For a grid named grid: grid.length gives the row count, grid[0].length gives the column count of the first row, and grid[row][col] reaches one cell. Always row first, column second.

โš ๏ธ Common Mistakes

A few 2D array slip-ups to watch for.

  • Swapping row and column. grid[row][col] means row first, column second. Writing grid[col][row] reaches the wrong cell or goes out of bounds.

The lines below show the wrong order versus the right order.

int value = grid[col][row]; // โŒ swapped, reads the wrong cell
int value = grid[row][col]; // โœ… row first, then column
  • Assuming all rows are the same length. Rows can be jagged. So the inner loop must use each rowโ€™s own length.
for (int col = 0; col < grid.length; col++) // โŒ uses the row count for columns
for (int col = 0; col < grid[row].length; col++) // โœ… uses this row's column count
  • Wrong bounds (off by one). Indexes go from 0 to length minus 1. Using <= runs one step too far and crashes with an out-of-bounds error.
for (int row = 0; row <= grid.length; row++) // โŒ <= goes one past the end
for (int row = 0; row < grid.length; row++) // โœ… < stops at the last valid row
  • Forgetting it is an array of arrays. A 2D array is rows, and each row is its own array. That is why you index it twice and why each row can have its own length.

โœ… Best Practices

Habits for clean 2D arrays.

  • Think rows first, columns second. Use that order both for indexing (grid[row][col]) and for your loops.
  • Let the array tell you its sizes. Use grid.length and grid[row].length instead of hard-coding numbers. Then the code still works if the grid changes size.
  • Name loop variables row and col. It reads like the problem and stops you from swapping them.
  • Use a 2D array for table-shaped data. Boards, grids, seating charts, simple matrices.
  • Name the array for its data. Call it board, grid, seats, or marks so its shape is obvious to the next reader.
  • Reach for for-each when you only need values. Use the index loop when you also need the position.

๐Ÿงฉ What Youโ€™ve Learned

Quick recap:

  • โœ… A 2D array is an array of arrays, shaped like a table with rows and columns.
  • โœ… You reach a value with two indexes: grid[row][col], row first.
  • โœ… Create it with nested {...} for known values, or new type[rows][cols] for an empty grid.
  • โœ… Loop over it with a nested loop: outer for rows, inner for columns.
  • โœ… grid.length is the row count, grid[row].length is that rowโ€™s column count.
  • โœ… Rows can have different lengths. That is a jagged array, and it is why the inner loop uses each rowโ€™s own length.

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    What does a 2D array represent best?

    Why: A 2D array is shaped like a grid or table, with rows and columns.

  2. 2

    How do you read the value at row 1, column 2?

    Why: You use two indexes, row first then column: grid[1][2].

  3. 3

    What does grid.length give you for a 2D array?

    Why: grid.length is the number of rows; grid[row].length is the columns in that row.

  4. 4

    How do you visit every cell of a 2D array?

    Why: A nested loop walks the rows on the outside and the columns on the inside.

๐Ÿš€ Whatโ€™s Next?

You can now build single arrays and grids. Next, meet the built-in helper Java ships for arrays. It can sort, search, fill, copy, and print arrays in one line each, so you write far less loop code by hand.

Java Arrays Utility Class

Share & Connect