W3docs

Copiare gli Array in Java

Copia gli array Java con System.arraycopy, Arrays.copyOf, clone e metodi basati sugli stream.

Assegnare una variabile array a un'altra non copia nulla — crea semplicemente due nomi che puntano allo stesso array sottostante:

int[] a = {1, 2, 3};
int[] b = a;
b[0] = 99;
System.out.println(a[0]);   // 99 — same array

Per ottenere una copia indipendente è necessario richiederla esplicitamente. Java offre diversi modi, ciascuno adatto a una situazione diversa: duplicato completo, ridimensionamento durante la copia, slice, copia tra due array esistenti. La maggior parte di questi metodi si trova nella classe utility Arrays, quindi un import java.util.Arrays; è presupposto negli esempi seguenti.

Arrays.copyOf — duplicare o ridimensionare

Accetta la sorgente e una lunghezza di destinazione. Se la nuova lunghezza coincide, si ottiene una copia pulita. Se è maggiore, gli slot extra vengono riempiti con valori predefiniti (0, false, null); se è minore, la coda viene eliminata.

import java.util.Arrays;

int[] data = {1, 2, 3, 4, 5};
int[] same   = Arrays.copyOf(data, data.length);   // {1, 2, 3, 4, 5}
int[] grown  = Arrays.copyOf(data, 8);             // {1, 2, 3, 4, 5, 0, 0, 0}
int[] shrunk = Arrays.copyOf(data, 3);             // {1, 2, 3}

È così che si "espande" un array di dimensione immutabile — si alloca uno più grande e si copia.

Arrays.copyOfRange — slice

Copia un intervallo semiaperto [from, to):

int[] data = {1, 2, 3, 4, 5};
int[] middle = Arrays.copyOfRange(data, 1, 4);   // {2, 3, 4}

to può superare la lunghezza della sorgente — gli slot extra vengono restituiti come valori predefiniti. Quindi è possibile eseguire lo slice e il riempimento in una sola chiamata.

System.arraycopy — copiare in un array esistente

La primitiva di livello più basso: copia un intervallo di un array in un intervallo di un altro. Nessuna nuova allocazione, nessun valore restituito — entrambi gli array devono già esistere.

int[] src = {10, 20, 30, 40, 50};
int[] dst = new int[8];
System.arraycopy(src, 1, dst, 3, 3);
// dst is now {0, 0, 0, 20, 30, 40, 0, 0}

Gli argomenti sono (src, srcStart, dst, dstStart, length). Si usa questo metodo quando si vuole posizionare i dati a un offset specifico, o quando si spostano elementi all'interno dello stesso array — System.arraycopy(arr, i, arr, i + 1, length - i - 1) sposta uno slice a destra di uno per fare spazio a un inserimento. Gli intervalli sovrapposti all'interno di un singolo array sono supportati e gestiti correttamente.

clone() — copia completa rapida

Ogni array ha un metodo clone() che restituisce un nuovo array della stessa lunghezza e contenuto:

int[] data = {1, 2, 3};
int[] copy = data.clone();

Per gli array monodimensionali, clone() è il modo più breve e chiaro per duplicare. Il tipo restituito è lo stesso della sorgente — nessun cast necessario.

Per gli array multidimensionali, clone() è superficiale: copia l'array esterno, ma le righe sono ancora i riferimenti originali:

int[][] grid = {{1, 2}, {3, 4}};
int[][] shallow = grid.clone();
shallow[0][0] = 99;
System.out.println(grid[0][0]);   // 99 — same inner row

Per copiare in profondità un array 2D, si clona ogni riga a turno:

int[][] deep = new int[grid.length][];
for (int r = 0; r < grid.length; r++) deep[r] = grid[r].clone();

Una versione con stream: Arrays.stream(grid).map(int[]::clone).toArray(int[][]::new).

Stream

Per gli array di oggetti, Arrays.stream(arr).toArray(T[]::new) produce una copia:

String[] names = {"Ada", "Linus", "Grace"};
String[] copy = Arrays.stream(names).toArray(String[]::new);

Per gli array primitivi, si usa lo stream specializzato:

import java.util.stream.IntStream;

int[] data = {1, 2, 3, 4, 5};
int[] copy = IntStream.of(data).toArray();

Gli stream sono più pesanti di copyOf o clone() ed esistono principalmente per il caso di trasformazione.map(...) o .filter(...) a metà della pipeline — non per la semplice duplicazione.

Copie per riferimento vs. copie profonde

Per i tipi primitivi, ogni copia è completamente indipendente — i valori stessi vengono duplicati. Per gli array di oggetti, tutti i metodi di copia visti finora sono superficiali: duplicano l'array di riferimenti, ma ogni riferimento punta ancora allo stesso oggetto dell'originale.

StringBuilder[] src = { new StringBuilder("hi") };
StringBuilder[] copy = src.clone();
copy[0].append(" there");
System.out.println(src[0]);   // "hi there" — same StringBuilder

Di solito va bene — String, Integer e qualsiasi oggetto immutabile possono essere condivisi senza problemi. Se gli elementi sono mutabili e si ha bisogno di oggetti indipendenti, è necessario copiarli manualmente:

StringBuilder[] deep = new StringBuilder[src.length];
for (int i = 0; i < src.length; i++) deep[i] = new StringBuilder(src[i]);

Scegliere un metodo di copia

Cosa si vuoleUsare
Duplicato esatto di un array 1Darr.clone() oppure Arrays.copyOf(arr, arr.length)
Ridimensionare durante la copia (espandere/ridurre)Arrays.copyOf(arr, newLength)
Slice — copiare una parte di un arrayArrays.copyOfRange(arr, from, to)
Copiare in uno slot di un array esistenteSystem.arraycopy(...)
Copia profonda di un array 2Dclonare ogni riga in un ciclo
Copiare e trasformarestream (map, filter, poi toArray)

Un esempio pratico

java— editable, runs on the server

Cosa c'è dopo

Ora sai come creare, scorrere, cercare, ordinare e copiare gli array — il toolkit completo per lavorare con i contenitori a dimensione fissa di Java. Il prossimo argomento riguarda i metodi: come organizzare il codice in unità nominate e riutilizzabili che accettano parametri e restituiscono valori.

Esercizi

Pratica
Cosa restituisce arr.clone() per un int[][]?
Cosa restituisce arr.clone() per un int[][]?
Was this page helpful?