Java Multidimensional Arrays
Table of Contents + โ
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 0System.out.println(grid[1][2]); // โ
row 1, column 2Read 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
16๐ข 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 0grid[0][0] = 10;grid[0][1] = 20;grid[1][2] = 30;- A fresh
intgrid 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, notprintln, 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 34 5 6Watch 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 XO X OX 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).
totalresets 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 245Riya scored 225This 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 yetjagged[0] = new int[1]; // row 0 has 1 columnjagged[1] = new int[2]; // row 1 has 2 columnsjagged[2] = new int[3]; // row 2 has 3 columnsThis 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
12 34 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 columnscube[1][2][3] = 99; // floor 1, row 2, column 3You 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. Writinggrid[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 cellint 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 columnsfor (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 endfor (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.lengthandgrid[row].lengthinstead of hard-coding numbers. Then the code still works if the grid changes size. - Name loop variables
rowandcol. 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, ormarksso 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, ornew type[rows][cols]for an empty grid. - โ Loop over it with a nested loop: outer for rows, inner for columns.
- โ
grid.lengthis the row count,grid[row].lengthis 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
What does a 2D array represent best?
Why: A 2D array is shaped like a grid or table, with rows and columns.
- 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
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
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.