Arrays

A mutable data type.

ints, doubles, booleans, and Strings are all immutable data types.

A given value never changes.

We can compute new values from existing values but the existing values stay what they are.

For instance

int x = 1 + 2

When we added 1 and 2 and got 3 neither the 1 nor the 2 changed to 3.

Variables can vary though

int a = 10;
int b = a;

Clearly a and b have the same value.

Now we do this.

a = a + 1;

What do you think the values of a and b are now?

» a
11

a has changed.

» b
10

b has not changed.

This is why it’s so important to understand the difference between values and variables.

Values exist somewhere in the computer.

Variables are names that refer to those values.

Changing what a name refers to doesn’t have any effect on the value it used to refer to.

The values of mutable data types can change

Arrays

Arrays represent a collection of values.

Each element of the collection can be independently changed.

Array syntax

Initializing an array variable

String[] things = new String[] { "foo", "bar", "baz" };

An array of Strings with three elements.

Can be shortened to:

String[] things = { "foo", "bar", "baz" };

Latter syntax can only be used in a variable declaration.

An array literal in other contexts

new String[] { "foo", "bar", "baz" }

Use this if you want to pass an array to a method without declaring a variable: foo(new int[] { 1, 2, 3})

Creating an empty array

new String[10];

This creates an array of Strings that can hold ten elements.

The elements of the array are all set to the zero value for the type: 0 for int, 0.0 for double, false, for boolean, and null for all reference types.

In this case since String is a reference type we get an array filled with 10 nulls.

Array access expressions

array[i]

array is an array and i is an int. Refers to the i’th element of array.

i is called an index.

The first element of an array is at index 0.

Elements are like variables

Each element of an array is kind of like a variable.

  • It holds a value we can use in expressions.

  • We can assign new values to it.

Accessing elements

Given:

String[] things = { "foo", "bar", "baz" };

Then:

things[0] ⟹ "foo"
things[1] ⟹ "bar"
things[2] ⟹ "baz"

Assigning to elements

Assign to the first element of things.

things[0] = "quux";

After the assignment:

things[0] ⟹ "quux"

This is mutation!

Arrays have a length property.

things.length ⟹ 3

things[things.length - 1] ⟹  "baz"

Note that things.length is one bigger than the largest legal index into things.

Also remember that length is a instance variable, unlike length() on String which is a method.

Mutability

Make an array and assign it to a variable.

String[] strings1 = { "foo" };

Assign the value of the first variable to a new variable.

String[] strings2 = strings1;

Now mutate the array.

strings1[0] = "baz";

Array has changed

System.out.println(strings1[0]);

Prints: baz

An array, by any other name

would be just as mutated:

System.out.println(strings2[0]);

Also prints: baz

strings2 has changed because it's just another name for the same array.

strings1 and strings2 are two separate variables but their value is the same, namely a reference to the same underlying array.

int a = 10;
int b = 10;
int c = a;
a++;

Declare and initialize a.

Declare and initialize b.

Declare and initialize c to the value of a.

Increment a. Notice neither b nor c changes.

Drawn by the content build (build/memory-diagrams.ts) from the <code visualization="increment"> block in materials/slides/java/arrays/slides.deck a 10 b 10 c 10 11
int[] foo = { 10, 20, 30 };
int[] bar = foo;
int[] baz = { 10, 20, 30 };
foo[0] *= 10;
x = bar[0];
bar[0] = 0;

Allocate first array.

Assign reference to foo.

Assign the same reference to bar.

Allocate a second array.

Assign reference to the new array to baz.

Change the value of the first element of the first array using the variable foo.

Make a new int variable x and get its value from the array.

Change the value of the first element of the first array using the variable bar. Note that x doesn’t change.

Drawn by the content build (build/memory-diagrams.ts) from the <code visualization="arrays"> block in materials/slides/java/arrays/slides.deck length: 3 10 20 30 foo bar length: 3 10 20 30 baz 100 x 100 0
int[] foo = { 10, 20, 30 };
int[] bar = foo;
int[] baz = { 10, 20, 30 };
foo[0] *= 10;
x = bar[0];
bar[0] = 0;

Allocate first array.

Assign reference to foo.

Assign the same reference to bar.

Allocate a second array.

Assign reference to the new array to baz.

Change the value of the first element of the first array using the variable foo.

Make a new int variable x and get its value from the array.

Change the value of the first element of the first array using the variable bar. Note that x doesn’t change.

Drawn by the content build (build/memory-diagrams.ts) from the <code visualization="arrays-addresses"> block in materials/slides/java/arrays/slides.deck 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F length: 3 10 20 30 foo 0x05 bar 0x05 length: 3 10 20 30 baz 0x0A 100 x 100 0
int[] foo = { 10, 20, 30 };
int[] bar = new int[3];
bar[0] = foo[0];
bar[1] = foo[1]
bar[2] = foo[2];
foo[0] *= 10;

Allocate first array.

Assign reference to foo.

Allocate a new empty array.

Assign the reference to bar.

Copy the value at index 0 from foo to index 0 of bar.

Copy the value at index 1 from foo to index 1 of bar.

Copy the value at index 2 from foo to index 2 of bar.

Change the zeroth element of foo. Note that bar is unchanged.

Drawn by the content build (build/memory-diagrams.ts) from the <code visualization="arrays-2"> block in materials/slides/java/arrays/slides.deck 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F length: 3 10 20 30 foo 0x03 length: 3 0 0 0 bar 0x08 10 20 30 100
int[] foo = { 10, 20, 30 };
int[] bar = { 100, 200, 300 };
foo = bar;

Allocate first array.

Assign reference to foo.

Allocate second array.

Assign the reference to bar.

Assign bar to foo. Now both variables reference the second array.

The first array is now garbage since nothing references it. Its memory will be reclaimed by Java.

Drawn by the content build (build/memory-diagrams.ts) from the <code visualization="arrays-reassign"> block in materials/slides/java/arrays/slides.deck length: 3 10 20 30 foo length: 3 100 200 300 bar length: 3 10 20 30