dev only

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 is moduleCurrents.length - 1; the last valid column index is moduleCurrents[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.
  • .length gives the row count; .length on 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)