Jagged Arrays
A jagged array (also called a ragged array) is an array of arrays where each inner array can have a different length. Unlike a true rectangular 2D array, the rows in a jagged array don’t have to line up in columns — they can each be as long or as short as you need.
Why Use Jagged Arrays?
A regular multidimensional array allocates a perfect rectangle of memory — every row has the same number of columns. That’s fine when your data really is rectangular, but it wastes memory when rows naturally vary in size.
Imagine storing a triangle of numbers, or a monthly calendar where February has fewer days than July. A jagged array is the right tool for those jobs.
| Situation | Best choice |
|---|---|
| All rows same length | int[3][4] rectangular array |
| Rows have different lengths | Jagged array |
| Sparse or triangular data | Jagged array |
Declaring and Creating a Jagged Array
You create a jagged array by specifying only the number of rows upfront, then allocating each row separately.
// Declare an array with 3 rows — lengths unspecified yet
int[][] triangle = new int[3][];
// Allocate each row individually
triangle[0] = new int[1];
triangle[1] = new int[2];
triangle[2] = new int[3];
After this code, triangle[0] has 1 element, triangle[1] has 2, and triangle[2] has 3.
Initializing with Values
You can combine declaration and initialization using an array initializer:
int[][] jagged = {
{1},
{2, 3},
{4, 5, 6},
{7, 8, 9, 10}
};
This gives you a 4-row jagged array where row lengths grow from 1 to 4.
Accessing Elements
Access works the same way as any 2D array — array[row][column]. The difference is that valid column indices vary by row.
int[][] jagged = {
{10},
{20, 30},
{40, 50, 60}
};
System.out.println(jagged[0][0]); // 10
System.out.println(jagged[1][1]); // 30
System.out.println(jagged[2][2]); // 60
Output:
10
30
60
Warning: Accessing
jagged[0][1]above would throw anArrayIndexOutOfBoundsExceptionbecause row 0 only has one element. Always check the row length before indexing.
Iterating Over a Jagged Array
Use a nested loop, but read each row’s length dynamically using .length:
int[][] data = {
{1},
{2, 3},
{4, 5, 6}
};
for (int row = 0; row < data.length; row++) {
for (int col = 0; col < data[row].length; col++) {
System.out.print(data[row][col] + " ");
}
System.out.println();
}
Output:
1
2 3
4 5 6
You can also use a for-each loop since each inner array is just a regular int[]:
for (int[] row : data) {
for (int val : row) {
System.out.print(val + " ");
}
System.out.println();
}
The output is identical. The for-each version is cleaner when you don’t need the index.
Practical Example: Pascal’s Triangle
Pascal’s Triangle is a classic use case for jagged arrays — row n has exactly n + 1 elements.
public class PascalTriangle {
public static void main(String[] args) {
int rows = 5;
int[][] pascal = new int[rows][];
for (int i = 0; i < rows; i++) {
pascal[i] = new int[i + 1];
pascal[i][0] = 1;
pascal[i][i] = 1;
for (int j = 1; j < i; j++) {
pascal[i][j] = pascal[i - 1][j - 1] + pascal[i - 1][j];
}
}
for (int[] row : pascal) {
for (int val : row) {
System.out.print(val + " ");
}
System.out.println();
}
}
}
Output:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
A rectangular int[5][5] would allocate 25 cells; the jagged version allocates exactly 15 — the only cells that actually hold data.
Checking Row Lengths
You can inspect lengths at any time using .length:
int[][] jagged = {
{1, 2, 3},
{4, 5},
{6}
};
System.out.println("Number of rows: " + jagged.length);
for (int i = 0; i < jagged.length; i++) {
System.out.println("Row " + i + " length: " + jagged[i].length);
}
Output:
Number of rows: 3
Row 0 length: 3
Row 1 length: 2
Row 2 length: 1
See Array length for a full explanation of the .length property.
Jagged vs Rectangular 2D Arrays
// Rectangular — every row has exactly 4 columns (12 cells total)
int[][] rect = new int[3][4];
// Jagged — rows have 1, 2, and 3 columns (6 cells total)
int[][] jagged = new int[3][];
jagged[0] = new int[1];
jagged[1] = new int[2];
jagged[2] = new int[3];
| Feature | Rectangular | Jagged |
|---|---|---|
| Row lengths | All equal | Can vary |
| Memory | May waste space | Allocates exactly what’s needed |
| Access syntax | a[row][col] | a[row][col] (same) |
| Iteration | Simple nested loop | Nested loop using a[row].length |
| Use case | Matrix math, grids | Triangles, calendars, graphs |
Tip: When every row really does have the same number of columns, use a rectangular array — it’s simpler and the JVM can optimize sequential access more predictably.
Under the Hood
In Java, a 2D array is always an array of references to arrays — there is no native “matrix” type in the JVM. When you write int[][] rect = new int[3][4], the JVM creates:
- One
int[][]object on the heap holding 3 references. - Three separate
int[4]objects, each on the heap.
A jagged array is identical in structure — you’re just making each inner int[] a different size. The outer array still holds a reference to each row, regardless of how long that row is.
This also means:
- Each row is an independent object. You can reassign
jagged[1] = new int[10]at any time. - Row objects are not necessarily laid out next to each other in memory. For large matrices with many small rows, this can hurt cache performance compared to a single flat
int[]of sizerows * cols. jagged[i]is simply a reference (nulluntil you assign a row), so accessing an uninitialized row will throw aNullPointerException.
int[][] bad = new int[3][];
// bad[0] is null here — we never assigned a row
System.out.println(bad[0].length); // NullPointerException!
Warning: Always initialize every row before accessing it. A
nullrow looks valid from the compiler’s perspective but explodes at runtime.
For performance-critical numeric code (image processing, scientific computing), consider a flat int[] with manual index arithmetic (array[row * cols + col]) so all data is contiguous in memory. For most application code, jagged arrays are perfectly efficient.
Related Topics
- Multidimensional Arrays — rectangular 2D and higher-dimension arrays in Java
- Arrays — the foundation: declaration, indexing, and traversal
- Array length — how the
.lengthproperty works for both flat and nested arrays - for-each Loop — the cleanest way to iterate rows in a jagged array
- Arrays Utility Class — sorting, filling, copying, and comparing arrays with
java.util.Arrays - Array of Objects — applying the same jagged pattern with object references instead of primitives