Java Language Creazione e inizializzazione di matrici

Esempio

Casi di base

int[]   numbers1 = new int[3];                 // Array for 3 int values, default value is 0
int[]   numbers2 = { 1, 2, 3 };                // Array literal of 3 int values
int[]   numbers3 = new int[] { 1, 2, 3 };      // Array of 3 int values initialized
int[][] numbers4 = { { 1, 2 }, { 3, 4, 5 } };  // Jagged array literal
int[][] numbers5 = new int[5][];               // Jagged array, one dimension 5 long
int[][] numbers6 = new int[5][4];              // Multidimensional array: 5x4

Le matrici possono essere create usando qualsiasi tipo di primitivo o di riferimento.

float[]  boats = new float[5];          // Array of five 32-bit floating point numbers.
double[] header = new double[] { 4.56, 332.267, 7.0, 0.3367, 10.0 };
                                       // Array of five 64-bit floating point numbers.
String[] theory = new String[] { "a", "b", "c" };
                                       // Array of three strings (reference type).
Object[] dArt = new Object[] { new Object(), "We love Stack Overflow.", new Integer(3) };
                                       // Array of three Objects (reference type).

Per l'ultimo esempio, si noti che i sottotipi del tipo di array dichiarato sono consentiti nell'array.

Le matrici per i tipi definiti dall'utente possono anche essere costruite in modo simile ai tipi primitivi

UserDefinedClass[] udType = new UserDefinedClass[5];

Array, raccolte e flussi

Java SE 1.2
// Parameters require objects, not primitives

// Auto-boxing happening for int 127 here
Integer[]       initial        = { 127, Integer.valueOf( 42 ) };
List<Integer>   toList         = Arrays.asList( initial );  // Fixed size! 

// Note: Works with all collections
Integer[]       fromCollection = toList.toArray( new Integer[toList.size()] );

//Java doesn't allow you to create an array of a parameterized type
List<String>[]  list = new ArrayList<String>[2];  // Compilation error!
Java SE 8
// Streams - JDK 8+
Stream<Integer> toStream       = Arrays.stream( initial );
Integer[]       fromStream     = toStream.toArray( Integer[]::new );

Intro

Una matrice è una struttura di dati che contiene un numero fisso di valori primitivi o riferimenti a istanze di oggetti.

Ogni elemento in un array è chiamato un elemento e ogni elemento è accessibile tramite il suo indice numerico. La lunghezza di un array viene stabilita al momento della creazione dell'array:

int size = 42;
int[] array = new int[size];

La dimensione di un array è fissata al runtime quando inizializzata. Non può essere modificato dopo l'inizializzazione. Se la dimensione deve essere mutabile in fase di esecuzione, deve essere utilizzata una classe Collection come ArrayList . ArrayList archivia elementi in un array e supporta il ridimensionamento allocando un nuovo array e copiando gli elementi dal vecchio array.

Se l'array è di tipo primitivo, es

int[] array1 = { 1,2,3 };
int[] array2 = new int[10];

i valori sono memorizzati nella matrice stessa. In assenza di un inizializzatore (come in array2 sopra), il valore predefinito assegnato a ciascun elemento è 0 (zero).

Se il tipo di matrice è un riferimento a un oggetto, come in

SomeClassOrInterface[] array = new SomeClassOrInterface[10];

quindi la matrice contiene riferimenti a oggetti di tipo SomeClassOrInterface . Tali riferimenti possono fare riferimento a un'istanza di SomeClassOrInterface o qualsiasi sottoclasse (per le classi) o alla classe di implementazione (per le interfacce) di SomeClassOrInterface . Se la dichiarazione dell'array non ha inizializzatore, il valore predefinito di null viene assegnato a ciascun elemento.

Poiché tutti gli array sono int -indexed, la dimensione di un array deve essere specificata da un int . La dimensione dell'array non può essere specificata come una long :

long size = 23L;
int[] array = new int[size]; // Compile-time error:
                             // incompatible types: possible lossy conversion from
                             // long to int

Le matrici utilizzano un sistema di indice a base zero , il che significa che l'indicizzazione inizia da 0 e termina a length - 1 .

Ad esempio, l'immagine seguente rappresenta una matrice con dimensione 10 . Qui, il primo elemento si trova nell'indice 0 e l'ultimo elemento è nell'indice 9 , invece del primo elemento nell'indice 1 e nell'ultimo elemento nell'indice 10 (vedi figura sotto).

Un array di 10 elementi

Gli accessi agli elementi degli array vengono eseguiti in tempo costante . Ciò significa che l'accesso al primo elemento dell'array ha lo stesso costo (nel tempo) dell'accesso al secondo elemento, al terzo elemento e così via.

Java offre diversi modi per definire e inizializzare gli array, comprese le notazioni letterali e del costruttore . Quando si dichiarano gli array usando il new Type[length] costruttore new Type[length] , ogni elemento sarà inizializzato con i seguenti valori predefiniti:

Creazione e inizializzazione di matrici di tipi primitivi

int[] array1 = new int[] { 1, 2, 3 }; // Create an array with new operator and 
                                      // array initializer.
int[] array2 = { 1, 2, 3 };           // Shortcut syntax with array initializer.
int[] array3 = new int[3];            // Equivalent to { 0, 0, 0 }
int[] array4 = null;                  // The array itself is an object, so it
                                      // can be set as null.

Quando si dichiara un array, [] apparirà come parte del tipo all'inizio della dichiarazione (dopo il nome del tipo), o come parte del dichiaratore per una particolare variabile (dopo il nome della variabile), o entrambi:

int array5[];       /* equivalent to */  int[] array5;
int a, b[], c[][];  /* equivalent to */  int a; int[] b; int[][] c;
int[] a, b[];       /* equivalent to */  int[] a; int[][] b;
int a, []b, c[][];  /* Compilation Error, because [] is not part of the type at beginning
                       of the declaration, rather it is before 'b'. */    
// The same rules apply when declaring a method that returns an array:
int foo()[] { ... } /* equivalent to */  int[] foo() { ... }

Nell'esempio seguente, entrambe le dichiarazioni sono corrette e possono essere compilate ed eseguite senza problemi. Tuttavia, sia la convenzione di codifica Java che la Guida allo stile di Java di Google scoraggiano il modulo con parentesi dopo il nome della variabile: le parentesi identificano il tipo di matrice e dovrebbero apparire con la designazione del tipo . Lo stesso dovrebbe essere usato per le firme di ritorno del metodo.

float array[]; /* and */ int foo()[] { ... } /* are discouraged */
float[] array; /* and */ int[] foo() { ... } /* are encouraged */

Il tipo scoraggiato è pensato per accogliere gli utenti in transizione C , che hanno familiarità con la sintassi per C che ha le parentesi dopo il nome della variabile.

In Java, è possibile avere array di dimensione 0 :

int[] array = new int[0]; // Compiles and runs fine.
int[] array2 = {};        // Equivalent syntax.

Tuttavia, poiché si tratta di un array vuoto, non è possibile leggere da esso né assegnargli elementi:

array[0] = 1;     // Throws java.lang.ArrayIndexOutOfBoundsException.
int i = array2[0]; // Also throws ArrayIndexOutOfBoundsException.

Tali array vuoti sono in genere utili come valori di ritorno, in modo che il codice chiamante debba preoccuparsi solo di gestire un array, piuttosto che un potenziale valore null che può portare a una NullPointerException .

La lunghezza di un array deve essere un numero intero non negativo:

int[] array = new int[-1]; // Throws java.lang.NegativeArraySizeException

La dimensione dell'array può essere determinata utilizzando un campo finale pubblico chiamato length :

System.out.println(array.length); // Prints 0 in this case.

Nota : array.length restituisce la dimensione effettiva dell'array e non il numero di elementi dell'array a cui è stato assegnato un valore, diversamente da ArrayList.size() che restituisce il numero di elementi dell'array a cui è stato assegnato un valore.

Creazione e inizializzazione di array multidimensionali

Il modo più semplice per creare un array multidimensionale è il seguente:

int[][] a = new int[2][3];

Creerà due int arriys a[0] tre lunghezze: a[0] e a[1] . Questo è molto simile alla classica inizializzazione in stile C degli array rettangolari multidimensionali.

Puoi creare e inizializzare allo stesso tempo:

int[][] a = { {1, 2}, {3, 4}, {5, 6} };

A differenza di C , in cui sono supportati solo array rettangolari multidimensionali, gli array interni non devono necessariamente avere la stessa lunghezza o anche essere definiti:

int[][] a = { {1}, {2, 3}, null };

Qui, a[0] è un array int lunghezza singola, mentre a[1] è un array int due lunghezze e a[2] è null . Array come questo sono chiamati array frastagliati o array frastagliati , cioè sono matrici di array. Gli array multidimensionali in Java sono implementati come array di matrici, cioè array[i][j][k] è equivalente a ((array[i])[j])[k] . A differenza di C # , l' array[i,j] sintassi array[i,j] non è supportato in Java.

Rappresentazione di array multidimensionali in Java

Rappresentazione visiva di un array multidimensionale Java

Source - Live on Ideone

Creazione e inizializzazione di matrici di tipi di riferimento

String[] array6 = new String[] { "Laurel", "Hardy" }; // Create an array with new 
                                                      // operator and array initializer.
String[] array7 = { "Laurel", "Hardy" };              // Shortcut syntax with array 
                                                      // initializer.
String[] array8 = new String[3];                      // { null, null, null }
String[] array9 = null;                               // null

Vivi su Ideone

Oltre ai letterali e alle primitive String mostrati sopra, la sintassi di scelta rapida per l'inizializzazione dell'array funziona anche con tipi di Object canonici:

Object[] array10 = { new Object(), new Object() };

Poiché gli array sono covarianti, un array di tipi di riferimento può essere inizializzato come array di una sottoclasse, sebbene venga generata ArrayStoreException se si tenta di impostare un elemento su qualcosa di diverso da una String :

Object[] array11 = new String[] { "foo", "bar", "baz" };
array11[1] = "qux"; // fine
array11[1] = new StringBuilder(); // throws ArrayStoreException

La sintassi di scelta rapida non può essere utilizzata per questo perché la sintassi di scelta rapida avrebbe un tipo implicito di Object[] .

Un array può essere inizializzato con zero elementi utilizzando String[] emptyArray = new String[0] . Ad esempio, una matrice con lunghezza zero come questa viene utilizzata per la creazione di una Array da una Collection quando il metodo richiede il tipo di esecuzione di un oggetto.

In entrambi i tipi primitivi e di riferimento, un'inizializzazione di array vuota (ad esempio String[] array8 = new String[3] ) inizializzerà la matrice con il valore predefinito per ogni tipo di dati .

Creazione e inizializzazione di array di tipi generici

Nelle classi generiche, le matrici di tipi generici non possono essere inizializzate in questo modo a causa della cancellazione del tipo :

public class MyGenericClass<T> {
    private T[] a;

    public MyGenericClass() {
        a = new T[5]; // Compile time error: generic array creation
    }
}

Invece, possono essere creati usando uno dei seguenti metodi: (nota che questi genereranno avvisi non controllati)

  1. Creando una matrice Object e convertendola nel tipo generico:

    a = (T[]) new Object[5];
    

    Questo è il metodo più semplice, ma poiché l'array sottostante è ancora di tipo Object[] , questo metodo non fornisce sicurezza di tipo. Pertanto, questo metodo di creazione di un array viene utilizzato al meglio solo all'interno della classe generica, non è esposto pubblicamente.

  2. Usando Array.newInstance con un parametro di classe:

    public MyGenericClass(Class<T> clazz) {
        a = (T[]) Array.newInstance(clazz, 5);
    }
    

    Qui la classe di T deve essere esplicitamente passata al costruttore. Il tipo di ritorno di Array.newInstance è sempre Object . Tuttavia, questo metodo è più sicuro perché l'array appena creato è sempre di tipo T[] , e quindi può essere tranquillamente esternalizzato.

Riempimento di un array dopo l'inizializzazione

Java SE 1.2

Arrays.fill() può essere utilizzato per riempire una matrice con lo stesso valore dopo l'inizializzazione:

Arrays.fill(array8, "abc");        // { "abc", "abc", "abc" }

Vivi su Ideone

fill() può anche assegnare un valore a ciascun elemento dell'intervallo specificato dell'array:

Arrays.fill(array8, 1, 2, "aaa");  // Placing "aaa" from index 1 to 2.

Vivi su Ideone

Java SE 8

Dalla versione 8 di Java, è possibile utilizzare il metodo setAll e il relativo parallelSetAll Concurrent per impostare ogni elemento di un array su valori generati. Questi metodi sono passati a una funzione generatore che accetta un indice e restituisce il valore desiderato per quella posizione.

L'esempio seguente crea un array intero e imposta tutti i suoi elementi sul rispettivo valore di indice:

int[] array = new int[5];
Arrays.setAll(array, i -> i); // The array becomes { 0, 1, 2, 3, 4 }.

Vivi su Ideone

Dichiarazione separata e inizializzazione degli array

Il valore di un indice per un elemento dell'array deve essere un numero intero (0, 1, 2, 3, 4, ...) e inferiore alla lunghezza dell'array (gli indici sono a base zero). Altrimenti verrà lanciata una ArrayIndexOutOfBoundsException :

int[] array9;             // Array declaration - uninitialized
array9 = new int[3];      // Initialize array  - { 0, 0, 0 }
array9[0] = 10;           // Set index 0 value - { 10, 0, 0 }
array9[1] = 20;           // Set index 1 value - { 10, 20, 0 }
array9[2] = 30;           // Set index 2 value - { 10, 20, 30 }

Gli array non possono essere reinizializzati con la sintassi di scelta rapida di array initializer

Non è possibile inizializzare nuovamente un array tramite una sintassi di scelta rapida con un inizializzatore di array poiché un inizializzatore di array può essere specificato solo in una dichiarazione di campo o in una dichiarazione di variabile locale o come parte di un'espressione di creazione di matrice.

Tuttavia, è possibile creare un nuovo array e assegnarlo alla variabile utilizzata per fare riferimento al vecchio array. Mentre ciò comporta che l'array a cui fa riferimento tale variabile venga reinizializzato, il contenuto della variabile è un array completamente nuovo. Per fare ciò, il new operatore può essere utilizzato con un inizializzatore di array e assegnato alla variabile array:

// First initialization of array
int[] array = new int[] { 1, 2, 3 };

// Prints "1 2 3 ".
for (int i : array) {
    System.out.print(i + " ");
}

// Re-initializes array to a new int[] array.
array = new int[] { 4, 5, 6 };

// Prints "4 5 6 ".
for (int i : array) {
    System.out.print(i + " ");
}

array = { 1, 2, 3, 4 }; // Compile-time error! Can't re-initialize an array via shortcut 
                        // syntax with array initializer.

Vivi su Ideone