2D Array Creation and Access
Why 2D
Some data is naturally rows-and-columns, not just a flat list. Swerve drive telemetry is a good example: 4 modules (front-left, front-right, back-left, back-right), each logging several current-draw samples over time. That's a 2D array — one row per module, one column per sample.
// datatype[][] variableName = new datatype[numberRows][numberCols];
double[][] moduleCurrents = new double[4][5]; // 4 modules, 5 samples each
Java stores this as an array of arrays — the outer array holds 4 references, each pointing to its own 5-element inner array. Declared but not yet created (double[][] moduleCurrents; with no new), the variable is null, same as any other reference type. Once created with new, every element starts at that type's default (0.0 here).
Initializer Lists
An initializer list for a 2D array is a list of 1D initializer lists, one per row — size is inferred:
double[][] moduleCurrents =
{
{12.1, 11.8, 40.2, 12.4, 11.9}, // front-left
{12.0, 11.9, 12.1, 11.7, 12.2}, // front-right
{11.9, 12.3, 12.0, 11.8, 12.1}, // back-left
{12.2, 12.0, 11.9, 12.4, 11.9}, // back-right
};
Accessing Elements: arr[row][col]
The first index is the row, the second is the column:
double spike = moduleCurrents[0][2]; // front-left module, 3rd sample -> 40.2
moduleCurrents[0][2] = 0.0; // overwrite a bad reading
Printing a 2D array directly (System.out.println(moduleCurrents)) just prints its object reference, not its contents — printing every value takes nested loops (Lesson 10.2).
Row and Column Counts
The number of rows is .length; the number of columns is the length of any one row (AP CSA — and this curriculum — assumes every row has the same length, i.e. the array is rectangular, not "ragged"):
moduleCurrents.length // 4 (number of modules / rows)
moduleCurrents[0].length // 5 (samples per module / columns)
Valid row indices: 0 to length - 1. Valid column indices: 0 to arr[0].length - 1. An out-of-range index in either dimension throws ArrayIndexOutOfBoundsException, same as a 1D array.
Java Stores It as an Array of Arrays
Internally, moduleCurrents is one 4-element outer array, where each element is a reference to its own separate 5-element inner array — not one giant contiguous block. That's why moduleCurrents[0] alone is a valid expression: it's a real, complete double[] (front-left's row), which is what makes moduleCurrents[0].length work.
double[] frontLeftRow = moduleCurrents[0]; // a single row IS a real 1D array on its own
Common Pitfalls
- Swapping row and column.
moduleCurrents[2][0]is back-left's first sample, not front-left's third — the first index is always the row. - Assuming
new double[4][5]gives usable data. It gives 20 zeros, not real readings — same default-value rule as 1D arrays. - Off-by-one against
.length. The last valid row index ismoduleCurrents.length - 1; the last valid column index ismoduleCurrents[0].length - 1.
Key Takeaways
- A 2D array is declared/created as
datatype[][] name = new datatype[rows][cols];, or filled in one step with a nested initializer list (one inner list per row). arr[row][col]reads or writes one element; the first index is always the row, the second the column..lengthgives the row count;.lengthon any one row (e.g.arr[0].length) gives the column count.- Java implements a 2D array as an array of arrays — each row is itself a real, independent 1D array.
Derived from csawesome-2026: unit-4-data-collections/4.11-2d-array-creation-and-access.md (CSA 4.11)