Array Covariance

Object arrays are covariant, which means that just as Integer is a subclass of Number, Integer[] is a subclass of Number[]. This may seem intuitive, but can result in surprising behavior:

Integer[] integerArray = {1, 2, 3};
Number[] numberArray = integerArray;  // valid
Number firstElement = numberArray[0]; // valid
numberArray[0] = 4L;                  // throws ArrayStoreException at runtime

Although Integer[] is a subclass of Number[], it can only hold Integers, and trying to assign a Long element throws a runtime exception.

Note that this behavior is unique to arrays, and can be avoided by using a generic List instead:

List integerList = Arrays.asList(1, 2, 3);
//List numberList = integerList; // compile error
List numberList = integerList;
Number firstElement = numberList.get(0);
//numberList.set(0, 4L); // compile error

It’s not necessary for all of the array elements to share the same type, as long as they are a subclass of the array’s type:

interface I {}

class A implements I {}
class B implements I {}
class C implements I {}

I[] array10 = new I[] { new A(), new B(), new C() };// Create an array with new
                                                    // operator and array initializer.
I[] array11 = { new A(), new B(), new C() };        // Shortcut syntax with array
                                                    // initializer.
I[] array12 = new I[3];                             // { null, null, null }
I[] array13 = new A[] { new A(), new A() };         // Works because A implements I.
Object[] array14 = new Object[] { "Hello, World!", 3.14159, 42 };        // Create an array with
// new operator and array initializer.
Object[] array15 = { new A(), 64, "My String" };    // Shortcut syntax
                                                    // with array initializer.

Arrays to Stream

Version ≥ Java SE 8
Converting an array of objects to Stream:

String[] arr = new String[] {"str1", "str2", "str3"};
Stream stream = Arrays.stream(arr);

Converting an array of primitives to Stream using Arrays.stream() will transform the array to a primitive specialization of Stream:

int[] intArr = {1, 2, 3};
IntStream intStream = Arrays.stream(intArr);

You can also limit the Stream to a range of elements in the array. The start index is inclusive and the end index is exclusive:

int[] values = {1, 2, 3, 4};
IntStream intStream = Arrays.stream(values, 2, 4);

A method similar to Arrays.stream() appears in the Stream class: Stream.of(). The difference is that Stream.of() uses a varargs parameter, so you can write something like:

Stream intStream = Stream.of(1, 2, 3);
Stream stringStream = Stream.of("1", "2", "3");
Stream doubleStream = Stream.of(new Double[]{1.0, 2.0});

Iterating over arrays

You can iterate over arrays either by using enhanced for loop (aka foreach) or by using array indices:

int[] array = new int[10];
// using indices: read and write
for (int i = 0; i < array.length; i++) { array[i] = i; }

Version ≥ Java SE 5

// extended for: read only
for (int e : array) {
System.out.println(e);
}

It is worth noting here that there is no direct way to use an Iterator on an Array, but through the Arrays library it can be easily converted to a list to obtain an Iterable object.

For boxed arrays use Arrays.asList:

Integer[] boxed = {1, 2, 3};
Iterable boxedIt = Arrays.asList(boxed); // list-backed iterable
Iterator fromBoxed1 = boxedIt.iterator();

For primitive arrays (using java 8) use streams (specifically in this example – Arrays.stream -> IntStream):

int[] primitives = {1, 2, 3};
IntStream primitiveStream = Arrays.stream(primitives); // list-backed iterable
PrimitiveIterator.OfInt fromPrimitive1 = primitiveStream.iterator();

If you can’t use streams (no java 8), you can choose to use google’s guava library:

Iterable fromPrimitive2 = Ints.asList(primitives);

In two-dimensional arrays or more, both techniques can be used in a slightly more complex fashion.

Example:

int[][] array = new int[10][10];
for (int indexOuter = 0; indexOuter < array.length; indexOuter++) {
     for (int indexInner = 0; indexInner <          array[indexOuter].length; indexInner++) {
          array[indexOuter][indexInner] = indexOuter + indexInner;
     }
}

Version ≥ Java SE 5

for (int[] numbers : array) {
    for (int value : numbers) {
         System.out.println(value);
    }
}

It is impossible to set an Array to any non-uniform value without using an index based loop. Of course you can also use while or do-while loops when iterating using indices.

Related Article: Java Arrays

One note of caution: when using array indices, make sure the index is between 0 and array.length – 1 (both inclusive). Don’t make hard coded assumptions on the array length otherwise you might break your code if the array length changes but your hard coded values don’t.

Example:
int[] numbers = {1, 2, 3, 4};

public void incrementNumbers() {
    // DO THIS :
    for (int i = 0; i < numbers.length; i++) {
       numbers[i] += 1; //or this: numbers[i] = numbers[i] + 1; or numbers[i]++;
    }
    // DON'T DO THIS :
    for (int i = 0; i < 4; i++) {
        numbers[i] += 1;
    }
}

It’s also best if you don’t use fancy calculations to get the index but use the index to iterate and if you need different values calculate those.

Example:

public void fillArrayWithDoubleIndex(int[] array) {
    // DO THIS :
    for (int i = 0; i < array.length; i++) {
        array[i] = i * 2;
    }

    // DON'T DO THIS :
    int doubleLength = array.length * 2;
    for (int i = 0; i < doubleLength; i += 2) {
         array[i / 2] = i;
    }
}

Accessing Arrays in reverse order

int[] array = {0, 1, 1, 2, 3, 5, 8, 13};
for (int i = array.length - 1; i >= 0; i--) {
     System.out.println(array[i]);
}

Using temporary Arrays to reduce code repetition

Iterating over a temporary array instead of repeating code can make your code cleaner. It can be used where the same operation is performed on multiple variables.

// we want to print out all of these
String name = "Margaret";
int eyeCount = 16;
double height = 50.2;
int legs = 9;
int arms = 5;

// copy-paste approach:
System.out.println(name);
System.out.println(eyeCount);
System.out.println(height);
System.out.println(legs);
System.out.println(arms);

// temporary array approach:
for(Object attribute : new Object[]{name, eyeCount, height, legs, arms})
     System.out.println(attribute);

// using only numbers
for(double number : new double[]{eyeCount, legs, arms, height})
    System.out.println(Math.sqrt(number));

Keep in mind that this code should not be used in performance-critical sections, as an array is created every time the loop is entered, and that primitive variables will be copied into the array and thus cannot be modified.

Arrays to a String

Version ≥ Java SE 5

Since Java 1.5 you can get a String representation of the contents of the specified array without iterating over its every element. Just use Arrays.toString(Object[]) or Arrays.deepToString(Object[]) for multidimentional arrays:

int[] arr = {1, 2, 3, 4, 5};
System.out.println(Arrays.toString(arr));     // [1, 2, 3, 4, 5]
int[][] arr = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};
System.out.println(Arrays.deepToString(arr)); // [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

Arrays.toString() method uses Object.toString() method to produce String values of every item in the array, beside primitive type array, it can be used for all type of arrays. For instance:

public class Cat { /* implicitly extends Object */
        @Override
         public String toString() {
                 return "CAT!";
          }
}

Cat[] arr = { new Cat(), new Cat() };
System.out.println(Arrays.toString(arr)); // [CAT!, CAT!]

If no overridden toString() exists for the class, then the inherited toString() from Object will be used. Usually the output is then not very useful, for example:

public class Dog {
    /* implicitly extends Object */
}

Dog[] arr = { new Dog() };
System.out.println(Arrays.toString(arr));   // [Dog@17ed40e0]

How to Sort An Array in Java

Sorting arrays can be easily done with the Arrays api.

import java.util.Arrays;

// creating an array with integers
int[] array = {7, 4, 2, 1, 19};
// this is the sorting part just one function ready to be used
Arrays.sort(array);
// prints [1, 2, 4, 7, 19]
System.out.println(Arrays.toString(array));

Java Sorting String arrays:

String is not a numeric data, it defines it’s own order which is called lexicographic order, also known as alphabetic order. When you sort an array of String using sort() method, it sorts array into natural order defined by Comparable interface, as shown below :

Increasing Order

String[] names = {"John", "Steve", "Shane", "Adam", "Ben"};
System.out.println("String array before sorting : " + Arrays.toString(names));
Arrays.sort(names);
System.out.println("String array after sorting in ascending order : " + Arrays.toString(names));

Output:

String array before sorting : [John, Steve, Shane, Adam, Ben]
String array after sorting in ascending order : [Adam, Ben, John, Shane, Steve]

Decreasing Order

Arrays.sort(names, 0, names.length, Collections.reverseOrder());
System.out.println("String array after sorting in descending order : " + Arrays.toString(names));

Output:

String array after sorting in descending order : [Steve, Shane, John, Ben, Adam]

Sorting an Object array

In order to sort an object array, all elements must implement either Comparable or Comparator interface to define the order of the sorting.

We can use either sort(Object[]) method to sort an object array on its natural order, but you must ensure that all elements in the array must implement Comparable.

Furthermore, they must be mutually comparable as well, for example e1.compareTo(e2) must not throw a ClassCastException for any elements e1 and e2 in the array. Alternatively you can sort an Object array on custom order using sort(T[], Comparator) method as shown in following example.

// How to Sort Object Array in Java using Comparator and Comparable
Course[] courses = new Course[4];
courses[0] = new Course(101, "Java", 200);
courses[1] = new Course(201, "Ruby", 300);
courses[2] = new Course(301, "Python", 400);
courses[3] = new Course(401, "Scala", 500);
System.out.println("Object array before sorting : " + 
Arrays.toString(courses));

Arrays.sort(courses);
System.out.println("Object array after sorting in natural order : " + Arrays.toString(courses));

Arrays.sort(courses, new Course.PriceComparator());
System.out.println("Object array after sorting by price : " + Arrays.toString(courses));

Arrays.sort(courses, new Course.NameComparator());
System.out.println("Object array after sorting by name : " + Arrays.toString(courses));

Output:

Object array before sorting : [#101 Java@200 , #201 Ruby@300 , #301 Python@400 , #401 Scala@500 ]
Object array after sorting in natural order : [#101 Java@200 , #201 Ruby@300 , #301 Python@400 ,
#401 Scala@500 ]
Object array after sorting by price : [#101 Java@200 , #201 Ruby@300 , #301 Python@400 , #401
Scala@500 ]
Object array after sorting by name : [#101 Java@200 , #301 Python@400 , #201 Ruby@300 , #401
Scala@500 ]

Leave a Comment