Array in Java: una guida di riferimento

1. Introduzione

In questo tutorial, ci immergeremo in un concetto fondamentale del linguaggio Java: gli array.

Vedremo prima cos'è un array, quindi come usarli; nel complesso, vedremo come:

  • Inizia con gli array
  • Leggere e scrivere elementi di array
  • Esegui il loop su un array
  • Trasforma gli array in altri oggetti come List o Streams
  • Ordina, cerca e combina array

2. Cos'è un array?

Per prima cosa, dobbiamo definire cos'è un array? Secondo la documentazione Java, un array è un oggetto contenente un numero fisso di valori dello stesso tipo . Gli elementi di un array sono indicizzati, il che significa che possiamo accedervi con numeri (chiamati indici ).

Possiamo considerare un array come un elenco numerato di celle, ciascuna cella essendo una variabile che contiene un valore. In Java, la numerazione inizia da 0.

Esistono array di tipi primitivi e array di tipi di oggetti. Ciò significa che possiamo usare array di int, float, boolean, ... Ma anche array di String, Object e tipi personalizzati.

3. Configurazione di un array

Ora che gli array sono ben definiti, analizziamo i loro utilizzi.

Tratteremo molti argomenti che ci insegnano come usare gli array. Impareremo alcune nozioni di base come come dichiarare e inizializzare un array, ma tratteremo anche argomenti più avanzati come l'ordinamento e la ricerca di array.

Andiamo prima con la dichiarazione e l'inizializzazione.

3.1. Dichiarazione

Inizieremo con la dichiarazione. Esistono due modi per dichiarare un array in Java:

int[] anArray;

o:

int anOtherArray[];

Il primo è più ampiamente utilizzato del secondo .

3.2. Inizializzazione

Ora è il momento di vedere come inizializzare gli array. Anche in questo caso ci sono diversi modi per inizializzare un array. Vedremo i principali qui, ma questo articolo copre l'inizializzazione degli array in dettaglio.

Cominciamo con un modo semplice:

int[] anArray = new int[10];

Utilizzando questo metodo, abbiamo inizializzato un array di dieci elementi int . Nota che dobbiamo specificare la dimensione dell'array.

Quando si utilizza questo metodo, inizializziamo ogni elemento al suo valore predefinito , qui 0 . Quando si inizializza un array di Object , gli elementi sono nulli per impostazione predefinita.

Vedremo ora un altro modo che ci dà la possibilità di impostare i valori sull'array direttamente durante la creazione:

int[] anArray = new int[] {1, 2, 3, 4, 5};

Qui, abbiamo inizializzato un array di cinque elementi contenente i numeri da 1 a 5. Quando si utilizza questo metodo non è necessario specificare la lunghezza dell'array, è il numero di elementi poi dichiarato tra le parentesi graffe.

4. Accesso agli elementi

Vediamo ora come accedere agli elementi di un array. Possiamo ottenere ciò richiedendo una posizione della cella dell'array.

Ad esempio, questo piccolo frammento di codice stamperà 10 sulla console:

anArray[0] = 10; System.out.println(anArray[0]);

Nota come stiamo usando gli indici per accedere alle celle dell'array. Il numero tra parentesi è la posizione specifica dell'array a cui vogliamo accedere.

Quando si accede a una cella, se l'indice passato è negativo o va oltre l'ultima cella, Java lancerà un'eccezione ArrayIndexOutOfBoundException .

We should be careful then not to use a negative index, or an index greater than or equal to the array size.

5. Iterating Over an Array

Accessing elements one by one can be useful, but we might want to iterate through an array. Let's see how we can achieve this.

The first way is to use the for loop:

int[] anArray = new int[] {1, 2, 3, 4, 5}; for (int i = 0; i < anArray.length; i++) { System.out.println(anArray[i]); }

This should print numbers 1 to 5 to the console. As we can see we made use of the length property. This is a public property giving us the size of the array.

Of course, it's possible to use other loop mechanisms such as while or do while. But, as for Java collections, it's possible to loop over arrays using the foreach loop:

int[] anArray = new int[] {1, 2, 3, 4, 5}; for (int element : anArray) { System.out.println(element); }

This example is equivalent to the previous one, but we got rid of the indices boilerplate code. The foreach loop is an option when:

  • we don't need to modify the array (putting another value in an element won't modify the element in the array)
  • we don't need the indices to do something else

6. Varargs

We've already covered the basics when it comes to the creation and manipulation of arrays. Now, we'll dive into more advanced topics, beginning with varargs. As a reminder, varargs are used to pass an arbitrary number of arguments to a method:

void varargsMethod(String... varargs) {}

This method could take from 0 to an arbitrary number of String arguments. An article covering varargs can be found here.

What we have to know here is that inside the method body, a varargs parameter turns into an array. But, we can also pass an array directly as the argument. Let's see how by reusing the example method declared above:

String[] anArray = new String[] {"Milk", "Tomato", "Chips"}; varargsMethod(anArray);

Will behave the same as:

varargsMethod("Milk", "Tomato", "Chips");

7. Transforming an Array into a List

Arrays are great, but sometimes it can be handier to deal with List instead. We'll see here how to transform an array into a List.

We'll first do it the naïve way, by creating an empty list and iterating over the array to add its elements to the list:

int[] anArray = new int[] {1, 2, 3, 4, 5}; List aList = new ArrayList(); for (int element : anArray) { aList.add(element); }

But there is another way, a little bit more succinct:

Integer[] anArray = new Integer[] {1, 2, 3, 4, 5}; List aList = Arrays.asList(anArray);

The static method Arrays.asList takes a varargs argument and creates a list with the passed values. Unfortunately, this method comes with some drawbacks:

  • It's not possible to use an array of primitive types
  • We can't add or remove elements from the created list, as it'll throw an UnsupportedOperationException

8. From an Array to a Stream

We can now transform arrays into lists, but since Java 8 we have access to the Stream API and we might want to turn our arrays into Stream. Java provides us with the Arrays.stream method for that:

String[] anArray = new String[] {"Milk", "Tomato", "Chips"}; Stream aStream = Arrays.stream(anArray);

When passing an Object array to the method it will return a Stream of the matching type (e.g. Stream for an array of Integer). When passing a primitive one it will return the corresponding primitive Stream.

It's also possible to create the stream only on a subset of the array:

Stream anotherStream = Arrays.stream(anArray, 1, 3);

This will create a Stream with only “Tomato” and “Chips” Strings (the first index being inclusive while the second one is exclusive).

9. Sorting Arrays

Let's now see how to sort an array, that is rearranging its elements in a certain order. The Arrays class provides us with the sort method. A bit like the stream method, sort has a lot of overloadings.

There are overloadings to sort:

  • Primitive type arrays: which are sorted in ascending order
  • Object arrays (those Object must implement the Comparable interface): which are sorted according to the natural order (relying on the compareTo method from Comparable)
  • Generic arrays: which are sorted according to a given Comparator

In addition, it's possible to sort only a specific portion of an array (passing start and end indices to the method).

The algorithms behind the sort method are quick sort and merge sort for primitive and other arrays, respectively.

Let's see how this all work through some examples:

int[] anArray = new int[] {5, 2, 1, 4, 8}; Arrays.sort(anArray); // anArray is now {1, 2, 4, 5, 8} Integer[] anotherArray = new Integer[] {5, 2, 1, 4, 8}; Arrays.sort(anotherArray); // anotherArray is now {1, 2, 4, 5, 8} String[] yetAnotherArray = new String[] {"A", "E", "Z", "B", "C"}; Arrays.sort(yetAnotherArray, 1, 3, Comparator.comparing(String::toString).reversed()); // yetAnotherArray is now {"A", "Z", "E", "B", "C"}

10. Searching in an Array

Searching an array is pretty simple, we can loop over the array and search our element among the array elements:

int[] anArray = new int[] {5, 2, 1, 4, 8}; for (int i = 0; i < anArray.length; i++) { if (anArray[i] == 4) { System.out.println("Found at index " + i); break; } }

Here we searched for number 4 and found it at index 3.

If we have a sorted array though, we can use another solution: the binary search. The principle of binary search is explained in this article.

Fortunately, Java provides us with the Arrays.binarySearch method. We have to give it an array and an element to search.

In case of a generic array, we also have to give it the Comparator that was used to sort the array in the first place. There is again the possibility to call the method on a subset of the array.

Let's see an example of the binary search method usage:

int[] anArray = new int[] {1, 2, 3, 4, 5}; int index = Arrays.binarySearch(anArray, 4); System.out.println("Found at index " + index);

As we stored number 4 in the fourth cell, this will return index 3 as the result. Note that we used an already sorted array.

11. Concatenating Arrays

Finally, let's see how to concatenate two arrays. The idea is to create an array which length is the sum of the two arrays to concatenate. After that we have to add the elements of the first one and then the elements of the second one:

int[] anArray = new int[] {5, 2, 1, 4, 8}; int[] anotherArray = new int[] {10, 4, 9, 11, 2}; int[] resultArray = new int[anArray.length + anotherArray.length]; for (int i = 0; i < resultArray.length; i++) { resultArray[i] = (i < anArray.length ? anArray[i] : anotherArray[i - anArray.length]); }

As we can see, when the index is still lesser than the first array length we add elements from that array. Then we add elements from the second one. We can make use of the Arrays.setAll method to avoid writing a loop:

int[] anArray = new int[] {5, 2, 1, 4, 8}; int[] anotherArray = new int[] {10, 4, 9, 11, 2}; int[] resultArray = new int[anArray.length + anotherArray.length]; Arrays.setAll(resultArray, i -> (i < anArray.length ? anArray[i] : anotherArray[i - anArray.length]));

This method will set all array element according to the given function. This function associates an index with a result.

Ecco una terza opzione per unire gli array: System.arraycopy . Questo metodo accetta un array di origine , una posizione di origine, un array di destinazione , una posizione di destinazione e un int che definisce il numero di elementi da copiare:

System.arraycopy(anArray, 0, resultArray, 0, anArray.length); System.arraycopy(anotherArray, 0, resultArray, anArray.length, anotherArray.length);

Come possiamo vedere, copiamo il primo array, poi il secondo (dopo l'ultimo elemento del primo).

12. Conclusione

In questo articolo dettagliato abbiamo trattato gli usi di base e alcuni avanzati degli array in Java.

Abbiamo visto che Java offre molti metodi per gestire gli array tramite la classe di utilità Arrays . Esistono anche classi di utilità per manipolare gli array in librerie come Apache Commons o Guava.

Il codice completo per questo articolo può essere trovato sul nostro GitHub.