Processing Beginner Article 4

Arrays in Processing

Store and iterate over collections of values using fixed arrays and the flexible ArrayList.

⏱ 19 min arrays ArrayList particles data structures loops

What is an array?

An array is a numbered list of values, all of the same type, stored under a single variable name. Instead of declaring float x0, x1, x2, x3 … for twenty positions, you write one line and use an index to reach each element.

Declaring and initialising

There are two common ways to create an array in Processing (Java):

// 1. Declare then allocate — all elements start at 0 (or false/null)
float[] xs = new float[20];

// 2. Declare and initialise with literal values
int[]   primes   = { 2, 3, 5, 7, 11, 13 };
color[] palette  = { #E63946, #457B9D, #1D3557, #A8DADC };
String[] labels  = { "alpha", "beta", "gamma" };

Accessing elements

Elements are zero-indexed: the first is [0], the last is [length - 1].

float[] temps = { 18.2, 21.0, 19.5, 25.3, 22.8 };

println(temps[0]);             // 18.2
println(temps[temps.length - 1]); // 22.8

temps[2] = 20.1;               // overwrite the third element

Accessing an index outside the valid range throws an ArrayIndexOutOfBoundsException at runtime — check your index with conditionals or constrain() if in doubt.

Iterating with a for loop

float[] radii = new float[8];

// Populate
for (int i = 0; i < radii.length; i++) {
  radii[i] = 20 + i * 15;
}

// Draw concentric rings
void setup() {
  size(500, 500);
  background(15);
  noFill();
  stroke(100, 180, 255);
  strokeWeight(2);

  float[] rings = new float[8];
  for (int i = 0; i < rings.length; i++) {
    rings[i] = 20 + i * 28;
  }

  for (int i = 0; i < rings.length; i++) {
    ellipse(width / 2, height / 2, rings[i] * 2, rings[i] * 2);
  }
}

The enhanced for-each loop (Java 5+) is available too:

for (float r : rings) {
  ellipse(width / 2, height / 2, r * 2, r * 2);
}

ArrayList: dynamic sizing

A plain array has a fixed size set at creation. ArrayList grows and shrinks at runtime, which is essential for things like particle systems where objects are created and destroyed.

import java.util.ArrayList;

ArrayList<Float> sizes = new ArrayList<Float>();

sizes.add(10.0);           // append
sizes.add(25.5);
sizes.add(40.0);

println(sizes.get(0));     // 10.0
println(sizes.size());     // 3

sizes.remove(1);           // remove index 1 (25.5)
println(sizes.size());     // 2

In Processing, ArrayList requires the import. The type parameter <Float> specifies what kind of objects it holds. Use Float (capital F) rather than float because ArrayList works with objects, not primitives.

Particle trail example using ArrayList

import java.util.ArrayList;

ArrayList<PVector> trail = new ArrayList<PVector>();
int MAX_TRAIL = 60;

void setup() {
  size(700, 500);
  background(10);
}

void draw() {
  // Fade background slightly instead of clearing fully
  fill(10, 10, 10, 30);
  noStroke();
  rect(0, 0, width, height);

  // Add current mouse position to trail
  trail.add(new PVector(mouseX, mouseY));

  // Remove oldest point when trail is too long
  if (trail.size() > MAX_TRAIL) {
    trail.remove(0);
  }

  // Draw trail — older points are smaller and more transparent
  noStroke();
  for (int i = 0; i < trail.size(); i++) {
    float progress = (float) i / trail.size();
    float sz = map(progress, 0, 1, 2, 20);
    float alpha = map(progress, 0, 1, 0, 200);
    fill(100, 180, 255, alpha);
    PVector p = trail.get(i);
    ellipse(p.x, p.y, sz, sz);
  }
}

PVector is Processing’s built-in two-dimensional (and three-dimensional) vector class — a convenient way to bundle an x and y together.

2D arrays for grid-based data

A 2D array is an array of arrays. Declare it with two sets of brackets:

int COLS = 10;
int ROWS = 10;
float[][] grid = new float[ROWS][COLS];

// Fill with random values
for (int r = 0; r < ROWS; r++) {
  for (int c = 0; c < COLS; c++) {
    grid[r][c] = random(1);
  }
}

// Draw as colour swatches
void setup() {
  size(500, 500);
  int COLS = 10, ROWS = 10;
  float[][] grid = new float[ROWS][COLS];
  float cellW = width  / (float) COLS;
  float cellH = height / (float) ROWS;

  for (int r = 0; r < ROWS; r++) {
    for (int c = 0; c < COLS; c++) {
      grid[r][c] = random(1);
    }
  }

  noStroke();
  for (int r = 0; r < ROWS; r++) {
    for (int c = 0; c < COLS; c++) {
      float v = grid[r][c] * 255;
      fill(v, v * 0.5, 255 - v);
      rect(c * cellW, r * cellH, cellW, cellH);
    }
  }
}

2D arrays are the natural data structure for Conway’s Game of Life, cellular automata, image pixel data, and terrain height maps.

Choosing between array and ArrayList

Need Use
Fixed count, primitive values, maximum speed float[], int[]
Count changes at runtime, need add/remove ArrayList<T>
Store pairs of values (x, y) PVector or ArrayList<PVector>

Key takeaways

  • Fixed arrays (float[] xs = new float[n]) are zero-indexed and have a .length property.
  • Use a for loop with index to populate or read an array; use for-each when you only need the values.
  • ArrayList adds .add(), .get(i), .remove(i), and .size() — use it whenever the count changes.
  • 2D arrays (float[][] grid) are perfect for grid and image data.
  • PVector is Processing’s built-in way to bundle x/y (and z) coordinates into one object.