☕ Java
Multidimensional Array
A multidimensional array in Java is an array with more than two dimensions — an array of arrays of arrays, and so on. While two-dimensional arrays suffice for most programming tasks, three-dimensional arrays are used for spatial data (x, y, z coordinates of a 3D grid), volumetric data (layers, rows, columns), RGB pixel buffers, and scientific computations involving tensors. Java supports arbitrary dimensionality, though arrays beyond three dimensions are rare in practice.
Three-Dimensional Arrays
A three-dimensional array adds a third level of nesting to the array-of-arrays model. You can think of it as an array of 2D arrays — like a stack of matrices, or a cube of values. Each element is accessed with three indices: array[depth][row][column] or equivalently array[layer][row][col]. The length property at each level gives the count at that dimension.
Three-dimensional arrays arise naturally in data with three independent dimensions: a building has floors, each floor has rows of rooms, each row has individual rooms — a 3D array maps directly to this structure. A colour image has rows, columns, and colour channels (R, G, B) — a 3D array of byte or int represents this exactly. A simulation of a 3D physical space discretises the space into a grid of cells with x, y, z coordinates — a 3D array stores the value (temperature, pressure, density) at each cell.
The nested structure means traversal requires three nested loops, and printing for debugging requires Arrays.deepToString() because Arrays.toString() only formats the outermost dimension. The memory model is the same as for 2D arrays: three levels of reference indirection. The outermost array holds references to 2D sub-arrays, each of which holds references to 1D arrays, which hold the actual values.
Java
// ── Three-dimensional array — cube of values: ────────────────────────
// Represents a 3×4×5 data cube:
// 3 layers (depth), 4 rows per layer, 5 columns per row
int[][][] cube = new int[3][4][5];
// ── Dimensions: ───────────────────────────────────────────────────────
System.out.println("Depth (layers): " + cube.length); // 3
System.out.println("Rows per layer: " + cube[0].length); // 4
System.out.println("Cols per row: " + cube[0][0].length); // 5
System.out.println("Total elements: " +
(cube.length * cube[0].length * cube[0][0].length)); // 60
// ── Fill with computed values: ────────────────────────────────────────
int value = 1;
for (int d = 0; d < cube.length; d++) {
for (int r = 0; r < cube[d].length; r++) {
for (int c = 0; c < cube[d][r].length; c++) {
cube[d][r][c] = value++;
}
}
}
// cube[0][0] = [1,2,3,4,5], cube[0][1] = [6,7,8,9,10], etc.
// ── Access individual elements: ───────────────────────────────────────
System.out.println(cube[0][0][0]); // 1 — first element
System.out.println(cube[0][0][4]); // 5 — last in first row
System.out.println(cube[2][3][4]); // 60 — last element
// ── Three-level traversal: ────────────────────────────────────────────
for (int d = 0; d < cube.length; d++) {
System.out.println("Layer " + d + ":");
for (int r = 0; r < cube[d].length; r++) {
System.out.print(" Row " + r + ": ");
for (int c = 0; c < cube[d][r].length; c++) {
System.out.printf("%4d", cube[d][r][c]);
}
System.out.println();
}
}
// ── Arrays.deepToString — nested array printing: ──────────────────────
int[][][] small = {
{{1, 2}, {3, 4}},
{{5, 6}, {7, 8}}
};
System.out.println(Arrays.deepToString(small));
// [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]Practical 3D Array Applications
Three-dimensional arrays model data that inherently has three independent dimensions. Understanding how to map a real-world 3D structure to array indices is the key skill. The mapping should be natural and consistent: always the same meaning for each dimension, documented clearly, so that array[0][2][3] is unambiguously interpreted by any reader of the code.
An RGB image is a classic 3D array use case. The three dimensions are rows (height), columns (width), and colour channel (0=red, 1=green, 2=blue). A 1920×1080 RGB image would be represented as int[1080][1920][3] — 1080 rows of 1920 pixels, each pixel having 3 colour values. Accessing the red channel of the pixel at row 50, column 100 is img[50][100][0].
Building floor plans, game world chunks, and voxel grids all use 3D arrays naturally. The mental model is always a cube of cells where each cell holds a value, and the three indices address the cell's position in the three spatial dimensions.
Java
// ── Building floor plan: floors × rows × columns: ────────────────────
// Represents a 3-floor building, 4 rows of rooms, 5 rooms per row.
// Values: 0 = empty room, 1 = occupied, 2 = maintenance
int[][][] building = new int[3][4][5]; // [floors][rows][cols]
// Occupy some rooms:
building[0][1][2] = 1; // floor 0, row 1, room 2 occupied
building[1][0][0] = 1; // floor 1, row 0, room 0 occupied
building[2][3][4] = 2; // floor 2, row 3, room 4 maintenance
// Count occupied rooms per floor:
for (int floor = 0; floor < building.length; floor++) {
int occupied = 0;
for (int row = 0; row < building[floor].length; row++) {
for (int room = 0; room < building[floor][row].length; room++) {
if (building[floor][row][room] == 1) occupied++;
}
}
System.out.printf("Floor %d: %d rooms occupied%n", floor, occupied);
}
// ── RGB colour image processing: ─────────────────────────────────────
// Small 4×4 RGB image (rows × cols × channels): channels: 0=R, 1=G, 2=B
int[][][] image = new int[4][4][3];
// Set all pixels to red (R=255, G=0, B=0):
for (int r = 0; r < image.length; r++) {
for (int c = 0; c < image[r].length; c++) {
image[r][c][0] = 255; // Red channel
image[r][c][1] = 0; // Green channel
image[r][c][2] = 0; // Blue channel
}
}
// Convert to grayscale: gray = 0.299R + 0.587G + 0.114B
int[][] grayscale = new int[image.length][image[0].length];
for (int r = 0; r < image.length; r++) {
for (int c = 0; c < image[r].length; c++) {
int red = image[r][c][0];
int green = image[r][c][1];
int blue = image[r][c][2];
grayscale[r][c] = (int)(0.299*red + 0.587*green + 0.114*blue);
}
}
// ── Simple 3D voxel grid (game world chunk): ──────────────────────────
// 16×16×16 chunk, values = block type (0=air, 1=stone, 2=grass)
byte[][][] chunk = new byte[16][16][16]; // z=height, x=width, y=depth
// Fill bottom layer with stone:
for (int x = 0; x < 16; x++) {
for (int y = 0; y < 16; y++) {
chunk[0][x][y] = 1; // height 0 = stone
chunk[1][x][y] = 2; // height 1 = grass
}
}
// Count non-air blocks:
int blockCount = 0;
for (byte[][] layer : chunk) {
for (byte[] row : layer) {
for (byte block : row) {
if (block != 0) blockCount++;
}
}
}
System.out.println("Non-air blocks: " + blockCount); // 512 (2 full layers)Performance Considerations and Alternatives
Multidimensional arrays in Java suffer from a performance characteristic that becomes significant for large, performance-sensitive computations: each dimension adds a level of pointer indirection. Accessing element [d][r][c] in a 3D array requires three memory dereferences — follow the pointer from the outermost array to the 2D sub-array, follow the pointer to the 1D array, then read the value. Each dereference can be a cache miss if the inner arrays are scattered in memory.
For performance-critical code such as numerical computing, image processing, or physics simulation, a common optimisation is to flatten the multidimensional array into a single 1D array and compute the index manually. A 3D array of dimensions [D][R][C] maps to a 1D array of size D×R×C, and element [d][r][c] is at index d*(R*C) + r*C + c. This eliminates pointer chasing and keeps all data in a single contiguous block, which is much more cache-friendly.
Libraries like Apache Commons Math, EJML, and ND4J provide high-performance matrix and tensor operations that use optimised memory layouts and CPU intrinsics. For any serious numerical computing in Java beyond educational purposes, these libraries should be preferred over manually coded nested array operations.
Java
// ── Flattened 1D array for performance-critical 3D data: ─────────────
int DEPTH = 4, ROWS = 3, COLS = 5;
// Traditional 3D array — three levels of indirection:
int[][][] traditional = new int[DEPTH][ROWS][COLS];
// Flattened 1D array — contiguous memory, single indirection:
int[] flat = new int[DEPTH * ROWS * COLS];
// ── Index formula for flat array: ────────────────────────────────────
// [d][r][c] → d * (ROWS * COLS) + r * COLS + c
int d = 2, r = 1, c = 3;
int flatIndex = d * (ROWS * COLS) + r * COLS + c;
// ── Helper class for clean indexed access: ────────────────────────────
public class Array3D {
private final int[] data;
private final int depth, rows, cols;
public Array3D(int depth, int rows, int cols) {
this.depth = depth;
this.rows = rows;
this.cols = cols;
this.data = new int[depth * rows * cols];
}
public int get(int d, int r, int c) {
return data[d * rows * cols + r * cols + c];
}
public void set(int d, int r, int c, int value) {
data[d * rows * cols + r * cols + c] = value;
}
public int totalElements() { return data.length; }
}
Array3D arr = new Array3D(4, 3, 5);
arr.set(2, 1, 3, 42);
System.out.println(arr.get(2, 1, 3)); // 42
// ── When to use which: ────────────────────────────────────────────────
//
// int[][][] (nested array):
// ✓ Simple, readable code
// ✓ Dimensions can vary (jagged)
// ✓ Fine for small arrays or non-performance-critical code
// ✗ Multiple pointer dereferences — poor cache performance for large data
//
// int[] (flattened 1D):
// ✓ Single contiguous memory block
// ✓ Better cache performance for large arrays
// ✓ SIMD and JIT optimisations more effective
// ✗ Index computation required — less readable
// ✗ All dimensions must be fixed (no jagged structure)
//
// Library (ND4J, Apache Math, EJML):
// ✓ Highly optimised — uses native libraries, BLAS, LAPACK
// ✓ GPU support (ND4J)
// ✓ Rich API for operations
// ✗ External dependency
// → Best choice for production numerical computingRelated Topics in Arrays
Array Basics
An array in Java is a fixed-size, ordered collection of elements of the same type stored in a contiguous block of memory. Once created, the size of an array cannot change. Arrays are the simplest and most fundamental data structure in Java — they underlie many higher-level collections and provide direct, indexed access to elements in constant time O(1). Every array in Java is an object, inherits from java.lang.Object, and can hold either primitives or references.
One-Dimensional Array
A one-dimensional array is a linear sequence of elements of the same type, accessed by a single integer index. It is the simplest array form in Java and the foundation for understanding multidimensional arrays and collection classes. One-dimensional arrays are used to store and process lists of values — student grades, product prices, daily temperatures, character sequences — any time you need to work with a fixed-size ordered collection of homogeneous data.
Two-Dimensional Array
A two-dimensional array in Java is an array of arrays — each element of the outer array is itself a one-dimensional array. It is used to represent tabular data with rows and columns: matrices, game boards, spreadsheet grids, pixel buffers, and any data that is naturally organised in two dimensions. In Java, a 2D array is declared with two sets of brackets and accessed with two indices: array[row][column].
Jagged Array
A jagged array (also called a ragged array) is a multidimensional array where the inner arrays have different lengths. Unlike a rectangular 2D array where every row has the same number of columns, a jagged array allows each row to have its own independently sized inner array. This is possible because Java implements multidimensional arrays as arrays of arrays, making each inner array an independent object that can have any length.