web-dev-qa-db-fra.com

Passer ArrayList comme valeur uniquement et non comme référence

En termes simples, j'ai une méthode avec un paramètre ArrayList. Dans la méthode, je modifie le contenu de ArrayList à des fins uniquement pertinentes pour ce qui est renvoyé par la méthode. Par conséquent, je ne souhaite pas que la liste de tableaux qui est passée en tant que paramètre soit affectée (c'est-à-dire non passée en tant que référence).

Tout ce que j'ai essayé n'a pas réussi à obtenir l'effet désiré. Que dois-je faire pour pouvoir utiliser une copie de ArrayList au sein de la méthode uniquement, sans lui demander de modifier la variable réelle?

25
fvgs

Même si vous aviez un moyen de passer la liste de tableaux en tant que copie et non par référence, cela n'aurait été qu'une copie superficielle.

Je ferais quelque chose comme:

void foo(final ArrayList list) {

    ArrayList listCopy = new ArrayList(list);
    // Rest of the code

}

Et juste travailler sur la liste copiée.

37
Avi

Vous pouvez créer une copie de ArrayList à l'aide du constructeur de copie d'ArrayList:

ArrayList copy = new ArrayList(original);

Mais si les éléments de la liste sont également des objets, vous devez savoir que modifier un membre de la copie modifiera également ce membre dans l'original.

16
bchociej

Vous pouvez passer Collections#unmodifiableList(yourList) afin d’envoyer une copie non modifiable de votre liste. Au fait, votre List<Whatever> est passé par valeur puisque Java passe toujours par valeur , notez que dans la méthode foo(List<Whatever> list) vous ne pouvez pas modifier la valeur list mais vous pouvez en modifier le contenu.

public class MyClass {

    List<Whatever> list = new ArrayList<Whatever>();

    public void bar() {
        //filling list...
        foo(Collections.unmodifiableList(list));
    }

    public void foo(List<Whatever> list) {
        //do what you want with list except modifying it...
    }
}
4
Luiggi Mendoza

Je ne sais pas pourquoi, même après new ArrayList<MyObj>(old), l'objet changeait encore de référence dans des endroits où il n'était pas censé. J'ai donc dû instancier une nouvelle copie des objets à l'intérieur.

J'ai fait un constructeur de copie comme celui sur ArrayList et ai aimé

 newArray = new ArrayList<MyObj>();
        for (int i = 0; i < oldArray.size(); i++) {
            newArray.add(new MyObj(ondArray.get(i)));
        }

Espérez juste aider quelqu'un d'autre si la réponse d'Avi n'est pas suffisante dans votre cas, comme le mien avec un code trop compliqué pour comprendre même = P

3
Caio Faustino

Vous pouvez utiliser la méthode .clone ou une CopyOnWriteArrayList pour effectuer une copie, sans affecter l’original.

3
helion3

Essayez ceci dans votre méthode:

void method(List<Integer> list) {
        List copyList =  new ArrayList<Integer>();
        copyList.addAll(list); // This will create a copy of all the emlements of your original list
    }
2
Ankur Shanbhag

Il suffit de le cloner.

public ArrayList cloneArrayList(ArrayList lst){
    ArrayList list = new ArrayList();
    for (int i=0; i<lst.size(); i++){
        list.add(lst.get(i));
    }
    return list;
}

Ajouter suggéré dans les commentaires, vous pouvez également utiliser

ArrayList copy = new ArrayList(original);

et aussi

ArrayList copy = new ArrayList();
copy.addAll(original);

Sur les lignes des réponses existantes mais en utilisant l'API ArrayList. Vous pouvez utiliser la méthode subList(fromIndex, toIndex). Il crée explicitement une vue de la liste avec uniquement les éléments souhaités (bien sûr, en séquence). Ici, même si vous modifiez la vue avec les opérations ajouter/supprimer, etc., la liste d'origine ne sera pas modifiée. Cela vous évite de créer explicitement une copie.

Quelque chose comme ça:

public void recursiveMethod(List<Integer> list) {
    if(base)
         return;
    recursiveCall(list);

    // following will just create a tail list but will not actually modify the list
    recursiveCall(list.subList(1, list.size());
}
0
Parth