web-dev-qa-db-fra.com

Faire une copie d'un tableau

J'ai un tableau a qui est constamment mis à jour. Disons a = [1,2,3,4,5]. Je dois faire une copie exacte de a et l'appeler b. Si a devait changer en [6,7,8,9,10], b devrait toujours être [1,2,3,4,5]. Quelle est la meilleure façon de procéder? J'ai essayé une boucle for comme:

for(int i=0; i<5; i++) {
    b[i]=a[i]
}

mais cela ne semble pas fonctionner correctement. N'utilisez pas de termes avancés tels que copie profonde, etc., car je ne sais pas ce que cela signifie.

324
badcoder

Vous pouvez essayer d'utiliser System.arraycopy ()

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

System.arraycopy( src, 0, dest, 0, src.length );
533
Bala R

vous pouvez utiliser

int[] a = new int[]{1,2,3,4,5};
int[] b = a.clone();

ainsi que.

220
MeBigFatGuy

Si vous voulez faire une copie de:

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

C'est la voie à suivre:

int[] b = Arrays.copyOf(a, a.length);

Arrays.copyOf peut être plus rapide que a.clone() sur de petits tableaux. Les deux éléments copiés sont également rapides, mais clone () renvoie Object. Le compilateur doit donc insérer un transtypage implicite vers int[]. Vous pouvez le voir dans le bytecode, quelque chose comme ceci:

ALOAD 1
INVOKEVIRTUAL [I.clone ()Ljava/lang/Object;
CHECKCAST [I
ASTORE 2
170
Evgeniy Dorofeev

Belle explication de http://www.journaldev.com/753/how-to-copy-arrays-in-Java

Méthodes de copie de tableaux Java

Object.clone () : La classe Object fournit la méthode clone () et dans la mesure où array dans Java est également un objet, vous pouvez utiliser cette méthode pour obtenir une copie complète du tableau. Cette méthode ne vous conviendra pas si vous voulez une copie partielle du tableau.

System.arraycopy () : La classe System arraycopy () est le meilleur moyen de créer une copie partielle d'un tableau. Il vous permet de spécifier facilement le nombre total d'éléments à copier et les positions d'index des tableaux source et cible. Par exemple System.arraycopy (source, 3, destination, 2, 5) copie 5 éléments de la source à la destination, à partir du 3ème index de la source vers 2ème index de destination.

Arrays.copyOf (): Si vous souhaitez copier les premiers éléments d'un tableau ou une copie complète d'un tableau, vous pouvez utiliser cette méthode. Bien sûr, il n’est pas aussi polyvalent que System.arraycopy (), mais il n’est pas déroutant et facile à utiliser.

Arrays.copyOfRange () : Si vous voulez copier quelques éléments d’un tableau, où l’index de départ n’est pas 0, vous pouvez utiliser cette méthode pour copier tableau partiel.

51

J'ai le sentiment que toutes ces "meilleures façons de copier un tableau" ne vont pas vraiment résoudre votre problème.

Vous dites

J'ai essayé une boucle comme [...] mais cela ne semble pas fonctionner correctement?

En regardant cette boucle, il y a pas de raison évidente pour que cela ne fonctionne pas ... à moins que:

  • vous avez en quelque sorte les tableaux a et b en désordre (par exemple, a et b font référence au même tableau), ou
  • votre application est multi-thread et que différents threads lisent et mettent à jour le tableau a simultanément.

Dans les deux cas, d'autres méthodes de copie ne résoudront pas le problème sous-jacent.

La solution pour le premier scénario est évidente. Pour le deuxième scénario, vous devrez trouver un moyen de synchroniser les threads. Les classes de tableaux atomiques ne sont d'aucune aide, car elles ne disposent pas de constructeurs de copie atomique ni de méthodes de clonage, mais la synchronisation à l'aide d'un mutex primitif fera l'affaire.

(Il y a des allusions dans votre question qui me portent à penser qu'il s'agit bien d'un fil; par exemple, votre affirmation selon laquelle a est en constante évolution.)

31
Stephen C

Vous pouvez essayer d'utiliser Arrays.copyOf () en Java

int[] a = new int[5]{1,2,3,4,5};
int[] b = Arrays.copyOf(a, a.length);
11

Vous pouvez également utiliser Arrays.copyOfRange .

Exemple :

_public static void main(String[] args) {
    int[] a = {1,2,3};
    int[] b = Arrays.copyOfRange(a, 0, a.length);
    a[0] = 5;
    System.out.println(Arrays.toString(a)); // [5,2,3]
    System.out.println(Arrays.toString(b)); // [1,2,3]
}
_

Cette méthode est similaire à Arrays.copyOf , mais elle est plus flexible. Les deux utilisent _System.arraycopy_ sous le capot.

Voir :

7
ROMANIA_engineer

Toutes les solutions qui appellent longueur depuis array, ajoutent votre code redondant à zéro checkersconsider exemple:

int[] a = {1,2,3,4,5};
int[] b = Arrays.copyOf(a, a.length);
int[] c = a.clone();

//What if array a comes as local parameter? You need to use null check:

public void someMethod(int[] a) {
    if (a!=null) {
        int[] b = Arrays.copyOf(a, a.length);
        int[] c = a.clone();
    }
}

Je vous recommande de ne pas inventer la roue et d'utiliser la classe utilitaire où toutes les vérifications nécessaires ont déjà été effectuées. Considérons ArrayUtils de Apache commons. Votre code devient plus court:

public void someMethod(int[] a) {
    int[] b = ArrayUtils.clone(a);
}

Apache commons vous pouvez trouver

7
Cherry

Si vous devez travailler avec des tableaux bruts et pas ArrayList, alors Arrays a ce qu'il vous faut. Si vous regardez le code source, ce sont les meilleurs moyens d’obtenir une copie d’un tableau. Ils ont une bonne programmation défensive, car la méthode System.arraycopy() génère de nombreuses exceptions non vérifiées si vous lui indiquez des paramètres illogiques.

Vous pouvez utiliser l'un des éléments Arrays.copyOf() qui copiera le premier élément dans le Nth élément du nouveau tableau plus court.

_public static <T> T[] copyOf(T[] original, int newLength)
_

Copie le tableau spécifié, en tronquant ou en complétant avec des valeurs NULL (si nécessaire) afin que la copie ait la longueur spécifiée. Pour tous les index valides dans le tableau d'origine et dans la copie, les deux tableaux contiendront des valeurs identiques. Pour tous les index valides dans la copie mais pas dans l'original, la copie contiendra null. De tels index existeront si et seulement si la longueur spécifiée est supérieure à celle du tableau d'origine. Le tableau résultant a exactement la même classe que le tableau d'origine.

_2770
2771    public static <T,U> T[] More ...copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
2772        T[] copy = ((Object)newType == (Object)Object[].class)
2773            ? (T[]) new Object[newLength]
2774            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
2775        System.arraycopy(original, 0, copy, 0,
2776                         Math.min(original.length, newLength));
2777        return copy;
2778    }
_

ou Arrays.copyOfRange() fera également l'affaire:

_public static <T> T[] copyOfRange(T[] original, int from, int to)
_

Copie la plage spécifiée du tableau spécifié dans un nouveau tableau. L'indice initial de la plage (from) doit être compris entre zéro et original.length, inclus. La valeur at original [from] est placée dans l'élément initial de la copie (sauf si == original.length ou de == à). Les valeurs des éléments suivants du tableau d'origine sont placées dans les éléments suivants de la copie. L'indice final de l'intervalle (to), qui doit être supérieur ou égal à, peut être supérieur à original.length, auquel cas la valeur null est placée dans tous les éléments de la copie dont l'indice est supérieur ou égal à l'original. longueur - de. La longueur du tableau retourné sera to-from. Le tableau résultant a exactement la même classe que le tableau d'origine.

_3035    public static <T,U> T[] More ...copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType) {
3036        int newLength = to - from;
3037        if (newLength < 0)
3038            throw new IllegalArgumentException(from + " > " + to);
3039        T[] copy = ((Object)newType == (Object)Object[].class)
3040            ? (T[]) new Object[newLength]
3041            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
3042        System.arraycopy(original, from, copy, 0,
3043                         Math.min(original.length - from, newLength));
3044        return copy;
3045    }
_

Comme vous pouvez le constater, ces deux fonctions ne sont que des fonctions d'emballage sur _System.arraycopy_ avec une logique défensive confirmant que ce que vous essayez de faire est valide.

System.arraycopy est le moyen le plus rapide pour copier des tableaux.

2
user177800

Pour une copie nullement sécurisée d'un tableau, vous pouvez également utiliser une option avec la méthode Object.clone() fournie dans ce réponse .

int[] arrayToCopy = {1, 2, 3};
int[] copiedArray = Optional.ofNullable(arrayToCopy).map(int[]::clone).orElse(null);
0
Nicolas Henneaux