Java Arrays

Java Arrays

You’re probably not the first one to wonder how arrays work in Java. And you haven’t found a clear answer yet! I have some good news… This post is all about understand how arrays work, how to create them, how to store data and much more. I promise, you won’t be disappointed!

Let’s dive into the world of those mysterious arrays!

What is an Array

Java Array

Java Arrays are part of primitive types. It means an array is part of the language syntax, not a class.

An Array data structure consists of a collection of elements stored sequentially and accessible through an index (usually an integer).

Arrays have some specificities you should be aware of:

  • Once allocated, arrays can’t be resized. If you want a bigger array, you must allocate a new one,
  • An integer index points to each box inside the array. Thus, an array cannot contain more than 4 billion objects,
  • Arrays can be multidimensional: in this case, an array may contain arrays,
  • Arrays are Clonable: you can clone (deep copy) an array,
  • And Arrays are Serializable, you can send them over the wire (provided that the objects stored within the array are serializable too).

Elements stored in an array of size n are accessible through index 0 to n-1.

Okay, let’s make things more practical and see some code.

Creating Arrays

To create an array, several syntaxes are possible.


package com.octoperf;

import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class ArrayTest {

  public static final String HELLO_WORLD = "Hello World!";

  @Test
  public void shouldCreate() {
    final String[] a = new String[] {HELLO_WORLD};
    assertEquals(1, a.length);

    final String[] b = new String[1];
    b[0] = HELLO_WORLD;
    assertEquals(1, b.length);

    final String c[] = new String[] {HELLO_WORLD};
    assertEquals(1, c.length);
  }
}


Let’s see the valid syntaxes to create an Array in Java:

  • final String[] a = new String[] {HELLO_WORLD}: this creates an array with the size set to the number of elements declared in the body. This is known as array literals syntax,
  • final String[] b = new String[1]; declares an array of size 1 with no elements inside (index 0 points to null),
  • final String c[] = new String[] {HELLO_WORLD};: same as the first case, but brackets are placed next to the variable name.

You can create arrays of any type:


Object[] objects;
Collection<?>[] collections;
short myShorts[];

The code above only declares the reference type, but no array is created at this point. One must use the new keyword to allocate a new array in memory.


int[] integers = new int[10];
boolean[] bools = new boolean[10];

It’s worth to mention creating arrays of primitives types will initialize each array value to the default primitive value:

  • int, short, long, double: default value is 0,
  • boolean: default value is true,
  • All other classes (String, MyClass…): default value is null.

Iterating using For Loop

As we have seen before, elements within an array are accessible through an index. The following code iterates over an Array using a for loop.


@Test
public void shouldIterate() {
  final String[] a = new String[] {"John Doe", "John Smith"};

  // Iterate using traditional for loop
  for (int i = 0; i < a.length; i++) {
    System.out.println(a[i]);
  }

  // Iterate using foreach
  for (final String name : a) {
    System.out.println(name);
  }
}

The traditional for loop works as following:

  • ìnt i = 0: the initial condition; create a counter which starts at 0,
  • i < a.length: execute another loop iteration until i == a.length,
  • i++: increment i between each loop iteration.

Also, arrays, like Iterable, can be iterated over using a foreach loop.

The code above outputs:

John Doe
John Smith

Now, let’s see the different kind of arrays we can create.

Arrays of Objects

This kind of array stores objects instead of just primitives.


private static final class Person {
  private final String firstname, lastname;

  private Person(final String firstname, final String lastname) {
    super();
    this.firstname = requireNonNull(firstname);
    this.lastname = requireNonNull(lastname);
  }

  @Override
  public String toString() {
    return firstname + " " + lastname;
  }
}

@Test
public void shouldOneDimensional() {
  final Person[] people = new Person[2];
  people[0] = new Person("John", "Doe");
  people[1] = new Person("John", "Smith");

  for (final Person person : people) {
    System.out.println(person);
  }
}

Here we have an array of Person, a class which extends Object like any class in Java. (even if not specified in the code)

The code outputs:

John Doe
John Smith

I have created an array with 2 memory spaces. Then, I have assigned 2 Person instances, to index 0 and index 1 respectively.

Array IndexOutOf BoundsException

In the case you try to access an index which is outside the array size, the code will throw an ArrayIndexOutOfBoundsException.


import org.junit.Test;

import static java.util.Objects.requireNonNull;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

public class ArrayTest {

  @Test(expected = ArrayIndexOutOfBoundsException.class)
  public void shouldOutOfBounds() {
    final Person[] people = new Person[2];
    people[0] = new Person("John", "Doe");
    people[1] = new Person("John", "Smith");

    System.out.println(people[2]);
  }
}

The JUnit above tests that accessing people[2] when people array size is 2 throws the expected exception.

Often people tend to forget that arrays have indexes ranging from 0 to n-1 when the array is of size n.

final int[] array = new int[5];
for (int i = 1; i <= array.length; i++)`{
    System.out.println(array[index]);
}

This code will throw the exception because the loop end condition i <= array.length is wrong. It should be i < array.length.

Passing Array to Method

Just like any other object, arrays can be passed as arguments to a method.


import org.junit.Test;
import java.util.Arrays;

public class ArrayTest {

  @Test
  public void shouldPassAsArgs() {
final String[] people = new String[2];
    String[0] = "John Doe";
    String[1] = "John Smith";
    print(people);
  }

  public void print(final String[] people) {
    System.out.println(Arrays.toString(people));
  }
}

Method returning an array

Methods can also define arrays as type of return.


import org.junit.Test;
import java.util.Arrays;

public class ArrayTest {

  @Test
  public void shouldPassAsArgs() {
    print(people());
  }

  private static String[] people() {
    final String[] people = new String[2];
    String[0] = "John Doe";
    String[1] = "John Smith";

    return people;
  }

  private static void print(final String[] people) {
    System.out.println(Arrays.toString(people));
  }
}

Manipulating Arrays

Arrays contains various methods for manipulating arrays (such as sorting and searching). This class also contains a static factory that allows arrays to be viewed as lists.

Resize an Array

Unfortunately, you can’t resize / grow an array in Java. You’d need to:

  • Create a new array of the desired size, and copy the data from the original array to the new array, using java.lang.System.arraycopy(...),

@Test
public void shouldCopyArray() {
  final Person[] people = new Person[2];
  people[0] = new Person("John", "Doe");
  people[1] = new Person("John", "Smith");

  final Person[] newPeople = new Person[3];
  System.arraycopy(people, 0, newPeople, 0, people.length);
  newPeople[2] = new Person("John", "Connor");

  System.out.println(Arrays.toString(newPeople));
}

  • Or Use the java.util.ArrayList class, which does this for you when you need to make the array bigger, (because it provides the facility to grow an array and get a copy of the array)

  @Test
  public void shouldCopyArray() {
    final Person[] people = new Person[2];
    people[0] = new Person("John", "Doe");
    people[1] = new Person("John", "Smith");

    final List<Person> arrayList = new ArrayList<>();
    arrayList.addAll(Arrays.asList(people));
    arrayList.add(new Person("John", "Connor"));

    final Person[] newPeople = arrayList.toArray(new Person[arrayList.size()]);
    System.out.println(Arrays.toString(newPeople));
  }
  • Or Use java.util.Arrays.copyOf(...) methods which returns a bigger array, with the contents of the original array.

@Test
public void shouldCopyArray() {
  final Person[] people = new Person[2];
  people[0] = new Person("John", "Doe");
  people[1] = new Person("John", "Smith");

  final Person[] newPeople = Arrays.copyOf(people, 3);
  newPeople[2] = new Person("John", "Connor");

  System.out.println(Arrays.toString(newPeople));
}

Since Java 5 you can use Arrays.toString(arr) or Arrays.deepToString(arr) (for arrays within arrays).

Object[] version calls object.toString() on each object in the array. The output is even decorated with the brackets.

Single dimension Arrays

String[] array = new String[] {Mary", "Glenn", "Dane"};
System.out.println(Arrays.toString(array));

Outputs:

[Mary, Glenn, Dane]

Nested Arrays.

final String[][] deepArray = new String[][] {{"John", "Smith"}, {"John", "Doe"}};
System.out.println(Arrays.deepToString(deepArray));

Outputs:

[[John, Smith], [John, Doe]]

Primitive Arrays

final double[] doubleArray = { 1.0, 2.0, 3.0 };
System.out.println(Arrays.toString(doubleArray));

Outputs:

[1.0, 2.0, 3.0]

Reverse an array

The following code shows how to reverse an array with a temporary variable.


final int[] arr = new int[] {1, 2, 3, 4};
for (int i = 0; i < arr.length / 2; i++) {
    final int temp = arr[i];
    arr[i] = arr[arr.length - i - 1];
    arr[arr.length - i - 1] = temp;
}

System.out.println(Arrays.toString(arr));

Outputs:

[3, 2, 1]

Check an Array contains a value

The simplest way is to convert the array to a list using java.util.Arrays:

Arrays.asList(arr).contains(myValue);

Since Java 8, it’s also possible to use the Streams API, to check whether an array of int, double or loncontains a value (by respectively using a IntStream, DoubleStream or LongStream).

final int[] arr = {1, 2, 3, 4};
final boolean contains = IntStream.of(arr).anyMatch(x -> x > 2);

Both are linear searches which translates to a O(n) algorithmic complexity.

Sum Array Values

Summing array values (when those values are int, long, short or double) is pretty straight-forward.

final int[] arr = {1, 2, 3, 4};

int sum = 0;
// Using traditional loop
for (int i = 0; i < arr.length; i++) {
  sum += arr[i];
}

// Using foreach loop
sum = 0;
for (final int value : arr) {
  sum += value;
}

Both ways yield the same result and are similar in performances. (linear time)

Conclusion

We’ve just scratched the surface of what’s possible to do with arrays in Java. There are just so many things we can do with arrays that it’s impossible to enumerate them all here. We hope this tiny introduction to this data structure helped you to understand how it works!

By - CTO.
Tags: Java Arrays Tutorial

Comments

 

Thank you

Your comment has been submitted and will be published once it has been approved.

OK

OOPS!

Your post has failed. Please return to the page and try again. Thank You!

OK