# ArrayList kopieren



## Tartaglia (11. Dez 2012)

Hallo zusammen,

ich versuche gerade eine arrayList zu kopieren und innerhalb der Kopie Veränderungen durchzuführen (Elemente entfernen z.B.). Ich habe allerdings den Verdacht, dass die Veränderungen auch auch in der ursprünglichen arrayList durchgeführt werden (ich erhalte einige Zeilen später eine Fehlermeldung, dass die ursprüngliche Liste leer sei). Ich habe es ursprünglich folgendermaßen gemacht:


```
agentList2 = agentList;
```

Wenn ich die Elemente jedoch einzeln in die neue Liste einfüge, erhalte ich die Fehlermeldung nicht, d.h. die usprüngliche Liste wird herbei nicht verändert.

for(int i = agentList.size()-1; i >=0 ; i--){
		  School s = (School)agentList.get(i);

		  agentList2.add(s);
	 }

Kann es sein, dass bei der ersten Variante, beide Listen ständig angeglichen werden, d.h. wann immer eine sich verändert, wird auch die andere angepasst?

Vielen Dank
Tartaglia


----------



## bone2 (11. Dez 2012)

mit der ersten Lösung kopierst du nur die referenz in eine zweite variable. beide variablen zeigen dann auf die gleiche Liste.

es gibt copy methoden, aber im endeffekt tut es deine schleife auch.


----------



## nillehammer (11. Dez 2012)

> Kann es sein, dass bei der ersten Variante, beide Listen ständig angeglichen werden, d.h. wann immer eine sich verändert, wird auch die andere angepasst?


Ja, denn Du erzeugst *keine* Kopie, sondern nur eine weitere Referenz auf die bestehende List. Nutze fürs kopieren am besten den Copy-Construktor 
	
	
	
	





```
new ArrayList(Collection)
```


----------



## Tartaglia (11. Dez 2012)

Das erklärt einiges, vielen Dank euch beiden!!!


----------



## Tartaglia (11. Dez 2012)

Jetzt ist doch noch ein Problem aufgetaucht, und zwar nehme ich ja an den Elementen der beiden arrayLists Änderungen vor (bestimmte Eigenschaften werden angepasst), jetzt werden diese Änderungen aber in den Elementen beider Listen vorbenommen, da es sich ja -wenn ich Euch richtig verstehe- auch hier nur um Referenzen auf die eigentlichen Objekte handelt (auch in meiner Variante mit der Schleife). 

Wie genau müsste ich denn z.B. mit dem Copy Constructor vorgehen, um die Elemente tatsächlich zu kopieren, damit die ursprünglichen Elemente der ursprünglichen Liste nicht verändert werden?

Ich habe es auf folgende Weise versucht, indem ich den copy constructor an meine obige Schleife angehängt habe (damit die arrayList auch genug Plätze hat):
[Java]
	 for(int i = arrayList.size()-1; i >=0 ; i--){
		  School s = (School)arrayList.get(i);
		  arrayList2.add(s);
		  	 }	 

	  Collections.copy(arrayList2,arrayList);
[/Java]
Jetzt müsste nach meinem Verständnis, die arrayList2 Duplikate der Elemente aus arrayList enthalten, d.h. wenn ich an diesen Objekten Änderungen vornehme, müssten die Objekte in der ersten Liste unverändert bleiben. Allerdings ist dem leider nicht so. Kann ich irgendwie erreichen, dass die Objekte wirklich dupliziert werden? Viell. mit clone()?

Danke 
Tartaglia


----------



## SlaterB (11. Dez 2012)

> auf folgende Weise versucht, indem ich den copy constructor an meine obige Schleife angehängt habe

Collections.copy() macht nicht viel besser als deine Schleife, 
wird sich jedenfalls hüten, neue Objekte zu erstellen statt mit den vorhandenen Objekten zu arbeiten

hier musst du ansetzen:
> School s = (School)arrayList.get(i);
s ist das alte Objekt, erstelle ein neues:
School s2 = new School(s);
oder clone() ja, Beispiele suchen


----------



## nillehammer (11. Dez 2012)

> Jetzt müsste nach meinem Verständnis, die arrayList2 Duplikate der Elemente aus arrayList enthalten, d.h. wenn ich an diesen Objekten Änderungen vornehme, müssten die Objekte in der ersten Liste unverändert bleiben. Allerdings ist dem leider nicht so. Kann ich irgendwie erreichen, dass die Objekte wirklich dupliziert werden? Viell. mit clone()?


Nein, das ist nicht so. Du hast jetzt zwar verschiedene "Schubladen" (die beiden Listen), aber das was drinnen ist, ist dasselbe, weil Du wieder nur Referenzen (in dem Fall Referenzen auf die Elemente) hin und herschiebst. Genau der gleiche Denkfehler wie bei Deinem ersten Versuch mit den Listen. Wenn Du unabhängige Kopien haben willst, musst Du immer etwas mehr machen als ein schlichtes:

```
// Erzeugt NIEMALS eine unabhängige Kopie,
// Egal, um was für einen Typen es sich hier handelt
variable1 = variable2;

// Das auch nicht, hier haben die Referenzen zwar keine
// Namen, sondern "stecken" in
// Containern, aber semantisch ist das nichts anderes als oben.
arrayList2.add(arrayList1.get(i));
```
Das "mehr Machen" kann ein geeigneter Konstruktor sein, der die Werte des Originals in die Kopie setzt, das kann eine clone()-Methode sein. Das kann eine statische Hilfsmethode sein(wie bei Collections.copy()) oder oder.


----------



## nillehammer (11. Dez 2012)

Dein Code ist etwas daneben (siehe Kommentare)


> ```
> // Hier kopierst Du die Elemente händisch
> for(int i = arrayList.size()-1; i >=0 ; i--){
> School s = (School)arrayList.get(i);
> ...


Eine Copy-Konstruktor bentutzt Du auch nicht, sondern die statische Hilfsmethode 
	
	
	
	





```
Collections.copy
```
. Das alleine reicht und wäre für einen allgemeinen Ansatz auch die beste Wahl. Da Du aber auch die Elemente kopieren willst, musst Du es sowieso *händisch machen*.


> (damit die arrayList auch genug Plätze hat):


Die Aussage ist Quatsch. Eine Liste ist ja (im Gegensatz zu einem Array) gerade etwas, das dynamisch wachsen kann. Sie hat also immer genug Plätze. Allein aus Optimierungsgründen kann es Sinn machen, ihr bei ihrer Erstellung eine initiale Größe mit zu geben.


----------



## Tartaglia (11. Dez 2012)

Vielen Dank für Eure Hinweise, ich habe zum Kopieren von Objekten auch gelesen, dass das nicht ganz unbedenklich ist. Ich muss daher nochmal mal meinen Code durchgehen, ob es wirklich notwendig ist.

@nillehammer: ich hatte die Fehlermeldung bekommen, dass der Platz in der Liste nicht ausreichend sei, deswegen habe ich die arraylist mit Platzhaltern gefüllt.


----------



## no0b (11. Dez 2012)

Suche mal nach flacher und tiefer Kopie.

Wenn du zeit hast, errate mal diese Ausgabe oder probiere es einfach aus:


```
static class Elem {
        private Object elem;
        public Elem(Object elem) {
            this.elem = elem;
        }
        public Object getElem() {
            return elem;
        }
        public void setElem(Object elem) {
            this.elem = elem;
        }
        @Override
        public String toString() {
            return elem.toString();
        }
    }

    public static void main(String[] args) {
        List<Elem> l1 = new ArrayList<Elem>(Arrays.asList(new Elem("eins"), new Elem("zwei"), new Elem("drei")));
        System.out.println("l1 = " + l1 + "\n");

        List<Elem> l2 = l1;
        l2.clear();
        System.out.println("l1 = " + l1);
        System.out.println("l2 = " + l2 + "\n");

        l1.addAll(Arrays.asList(new Elem("eins"), new Elem("zwei"), new Elem("drei")));
        System.out.println("l1 = " + l1);
        System.out.println("l2 = " + l2 + "\n");

        List<Elem> l3 = new ArrayList<Elem>(l2.size());
        for (Elem elem : l2) {
            l3.add(elem);
        }
        l3.get(1).setElem("Null");
        l1.remove(2);
        System.out.println("l1 = " + l1);
        System.out.println("l2 = " + l2);
        System.out.println("l3 = " + l3 + "\n");

        l2.add(new Elem("drei"));
        l3 = new ArrayList<Elem>(l1.size());
        for (Elem elem : l1) {
            l3.add(new Elem(elem.getElem()));
        }
        l1.get(1).setElem("zwei");
        System.out.println("l1 = " + l1);
        System.out.println("l2 = " + l2);
        System.out.println("l3 = " + l3 + "\n");
    }
```

Grüße

PS. Elem ist statische innere Klasse.


----------



## Tartaglia (12. Dez 2012)

Vielen Dank no0b, hab es jetzt erstmal ohne Kopieren hinbekommen, aber ich versuche mich später nochmal daran. Vielen Dank für den Hinweis auf jeden Fall!!


----------

