# Liste kopieren



## handoffate (31. Aug 2009)

Hi,

ich verzweifel gerade an meiner Liste..
Ich habe eine klassische Liste geschrieben, mit einer Klasse für die Knoten in der eigentlich nur die Daten stehen etc..
Eine weitere Klasse für die Liste mit Funktionen zum Einfügen, Löschen und anderen quatsch den man so brauchen kann...
Nun möchte ich die Liste kopieren:

```
public myList copy(){
mynode akt= head;
mylist result=new myList();
while(akt!=null){
result.insert(akt);
akt=akt.getNext();
}
return result;
}
```

habe ich da ein generelles Problem mit der herangehensweise??
ich handle mir damit eine Endlosschleife ein, wenn ich jedoch beim Einfügen einen NEUEN knoten erstelle funktioniert es!????


----------



## SlaterB (31. Aug 2009)

eine Endlosschleife ist doch kein Grund, den Computer oder das Gehirn auszuschalten,

erstelle dir eine Testliste mit drei Elementen 1, 2, 3
und wenn die Schleife mehr als 4x durchlaufen wird, dann gib dir zu jeden Knoten dessen Inhalt aus (1, 2, 3),
notfalls dessen genaue Verlinkung, eine eindeutige Id/ hashCode() für den Knoten usw.,
das kann man alles herausfinden


allgemein liegst du mit dem letzten Satz richtig, ein Knoten gehört zu einer Liste, den kannst du nicht einfach woanders einfügen,
schlimmstenfalls geht alles kaputt, bestenfalls ist nur die Originalliste unbrauchbar geworden,
erstelle die Kopie


----------



## handoffate (31. Aug 2009)

SlaterB hat gesagt.:


> allgemein liegst du mit dem letzten Satz richtig, ein Knoten gehört zu einer Liste, den kannst du nicht einfach woanders einfügen,
> schlimmstenfalls geht alles kaputt, bestenfalls ist nur die Originalliste unbrauchbar geworden,
> erstelle die Kopie



hmm aber wenn ich Java richtig verstanden habe läuft das ganze doch so:
der Knoten ist ein Objekt welches in meinem Speicher sein Dasein fristet. Beim Einfügen in die Liste bekommt diese doch "nur" einen Pointer auf den Speicherbereich in dem mein Objekt liegt.
Warum kann ich dann in eine andre Liste nicht einen Pointer auf den selben bereich packen???


----------



## faetzminator (31. Aug 2009)

handoffate hat gesagt.:


> Warum kann ich dann in eine andre Liste nicht einen Pointer auf den selben bereich packen???



Natürlich kannst du das, aber wenn in einer Liste das Objekt geändert wird, ist es natürlich auch in der anderen Liste geändert worden - es ist ja nunmal das gleiche Objekt. Du musst in [c]clone()[/c] alle Unterobjekte ebenfalls klonen.


----------



## handoffate (31. Aug 2009)

faetzminator hat gesagt.:


> Natürlich kannst du das, aber wenn in einer Liste das Objekt geändert wird, ist es natürlich auch in der anderen Liste geändert worden - es ist ja nunmal das gleiche Objekt. Du musst in [c]clone()[/c] alle Unterobjekte ebenfalls klonen.



das ist ja genau der sinn der angelegenheit.. was meinst du mit dem klonen??


----------



## SlaterB (31. Aug 2009)

eine Strickjacke besteht aus Strick-Faden, da kannst du doch beim Kopieren nicht den Faden aus der einen Jacke rausnehmen und in die andere Jacke einfügen

gut, beim Programmieren gibts Referenzen, theoretisch können beide Jacken die gleichen Fäden benutzen,
aber wenn dann bei der einen Jacke ein Ärmel abgeschnitten wird, dann auch gleichzeitig bei der anderen Jacke


----------



## Leroy42 (31. Aug 2009)

Elemente die selbst Listen sind
ebenenfalls (rekursiv) klonen.


----------



## faetzminator (31. Aug 2009)

handoffate hat gesagt.:


> das ist ja genau der sinn der angelegenheit.. was meinst du mit dem klonen??



Du implementierst die für dein Objekt zu implementierende Methode ebenfalls in den abhängigen Klassen und kannst es auf deren Objekte jeweils aufrufen. Wie bereits erwähnt gibt es da [c]clone()[/c], welches in der Java API bereits vorkommt. Du musst also mit [c]copy()[/c] das Rad nicht neu erfinden.


----------



## handoffate (31. Aug 2009)

Leroy42 hat gesagt.:


> Elemente die selbst Listen sind
> ebenenfalls (rekursiv) klonen.



hab ja keine elemente die listen sind...

ich versteh einfach nur nicht, warum der code oben nicht funktioniert..

dass ich damit zwei listen bekomme die praktisch die selben sind (mit den erwähnten nachteilen) ist mir klar (und das ist auch gewollt auch wenns in diesem Beispiel keinen sinn macht )


----------



## Shulyn (31. Aug 2009)

```
public myList copy(myList alt) {

mylist kopie = new myList();

for (mynode next:alt) {

kopie.add(alt.getWert());

}
return result;
}
```

Oder habe ich was falsch verstanden? Du hast 1 Liste und willst Sie Kopieren...


----------



## handoffate (31. Aug 2009)

Shulyn hat gesagt.:


> ```
> public myList copy(myList alt) {
> 
> mylist kopie = new myList();
> ...



ich verstehe zwar diese for-Schleife nicht so ganz, aber wenn ich das richtig sehe ist das doch eigentlich das gleiche was ich auch gemacht hab??

Also nochmal was ich wollte:
Ich habe eine Liste.. die möchte ich kopieren, also eine neue Liste erstellen in der die GLEICHEN Objekte stehen wie in der alten
(myList neu= alt; tuts zwar bringt mir aber nichts  )


----------



## faetzminator (31. Aug 2009)

Was für eine Liste denn? Erbt sie von [c]java.util.List[/c]? Dann kannst du einfach [c]clone()[/c] aufrufen. Ansonsten wär es hilfreich, wenn du die gesamte Klasse posten würdest.


----------



## handoffate (31. Aug 2009)

faetzminator hat gesagt.:


> Was für eine Liste denn? Erbt sie von [c]java.util.List[/c]? Dann kannst du einfach [c]clone()[/c] aufrufen. Ansonsten wär es hilfreich, wenn du die gesamte Klasse posten würdest.



ne erbt von gar nichts.. ist ganz "eigen" gebastelt..
also:
Klasse für die Knoten

```
public class dlnode {

	private String title;
	...
	private dlnode next;
	
	
	public dlnode(String title, String path, String description, String comment, String language) {
		this.title=title;
		this.path=path;
		this.description=description;
		this.comment=comment;
		this.language=language;
		this.next=null;
	}
	
//get und set Methoden
	
	public String toString(){
		return title+";"+path+";"+description+";"+comment+";"+language+"\n";
	}
}
```
Klasse für die Liste:

```
public class dlist {

	private dlnode head;
	//private int count;
	
	public dlnode getHead(){
		return this.head;
	}
	
	public dlist(){
		head=null;
		//count=0;
	}
	
	public void eraseList(){
		head=null;
		//count=0;
	}
	
	public boolean isEmpty(){
		if (this.head==null)
			return true;
		else
			return false;
	}
	
	public void sortedinsert(dlnode toinsert){
		dlnode akt=head;
		dlnode last=null;
		if (isEmpty()){
			head=toinsert;
			//count++;
		}
		else {
			while(akt!=null){
				if (akt.getTitle().compareTo(toinsert.getTitle())<0){
					if (akt.getNext()==null){
						akt.setnext(toinsert);
						//count++;
						break;
					}
					else{
					last=akt;
					akt=akt.getNext();
					}
				}
				else {
					last.setnext(toinsert);
					toinsert.setnext(akt);
					//count++;
					break;
				}
			}
		}
	}
	
	public dlist copy(){
		dlist res= new dlist();
		dlnode akt=head;
		while(akt!=null){
			res.sortedinsert(akt);
			akt=akt.getNext();
		}
		return res;
		
	}

	
	public String toString(){
		dlnode akt=head;
		String res="";
		if (isEmpty())
			return "Liste ist leer";
		else {
			while (akt!=null) {
				res+="Knoten:";
				res=res+akt.toString();
				akt=akt.getNext();
			}
			return res;
		}
		
	}
}
```

wie erwähnt macht die copy() probleme.. Der Rest klappt wunderbar.
clone() würde mir nichts bringen (da ich im endeffekt noch aussuchen möchte welche Knoten ich kopiere)


----------



## faetzminator (31. Aug 2009)

implementier ein clone() in dlnode (schreib doch bitte DlNode -> Konventionen) so etwas:

```
public Object clone() {
    return new dlnode(this.title, this.path, [...]);
}
```
Das rufst du z.B. jeweils mit [c]akt.getNext().clone()[/c] statt [c]akt.getNext()[/c] auf. Musst natürlich die [c]dlnode next[/c] noch setzen.


----------



## handoffate (31. Aug 2009)

faetzminator hat gesagt.:


> implementier ein clone() in dlnode (schreib doch bitte DlNode -> Konventionen) so etwas:
> 
> ```
> public Object clone() {
> ...



wo meinst du soll ich das aufrufen? nur in copy() oder auch in den anderen funktionen??

aber: wenn ich da ein clone() mache, erzeuge ich eine zweite Liste mit NEUEN Objekten.. Das heißt, wenn ich in einer der Listen etwas ändere wird die andere nichts davon mitbekommen. sehe ich richtig oder?


----------



## faetzminator (1. Sep 2009)

Genau, um das geht doch ein clone()/copy()...


----------



## Shulyn (1. Sep 2009)

handoffate hat gesagt.:


> aber: wenn ich da ein clone() mache, erzeuge ich eine zweite Liste mit NEUEN Objekten.. Das heißt, wenn ich in einer der Listen etwas ändere wird die andere nichts davon mitbekommen. sehe ich richtig oder?



Ja es sind dann NEUE Objekte mit dem Inhalt der alten. Oder willst du nur neue Referenzen haben? Dann würde ein NeueListe = AlteListe reichen!


----------



## handoffate (1. Sep 2009)

Shulyn hat gesagt.:


> Ja es sind dann NEUE Objekte mit dem Inhalt der alten. Oder willst du nur neue Referenzen haben? Dann würde ein NeueListe = AlteListe reichen!



Das ist ja mein Problem: Ich möchte keine NEUEN Objekte, da sich beide Listen vollkommen identisch verhalten sollen (änder ich etwas in der einen so soll es auch in der anderen geändert sein)
ein NeueListe = AlteListe bringt mir nichts: das Beispiel mit dem Copy war  vielleicht etwas irreführend. Ich möchte die Liste zwar kopieren, aber unter umständen nicht alle Knoten sondern nur eine Teilliste...


----------



## faetzminator (1. Sep 2009)

Dann kannst du einfach die jeweiligen Knoten in die neue Liste kopieren, falls xy zutrifft. Aber dann stimmt ja jeweils die getNext() nicht mehr, da du dort alle zurückbekommen würdest. Das Feld überschreiben darfst du auch nicht, da es sonst in der "alten" Liste nicht mehr stimmt. Es funktioniert also *nicht*, ohne alle Nodes zu kopieren. Ansonsten musst du die Daten und Nodeinfos strikt trennen. Du kannst einen Datencontainer haben, welcher sich in einer Node befindet. Diesen kopierst du in eine neue Node.


----------



## handoffate (1. Sep 2009)

faetzminator hat gesagt.:


> Dann kannst du einfach die jeweiligen Knoten in die neue Liste kopieren, falls xy zutrifft. Aber dann stimmt ja jeweils die getNext() nicht mehr, da du dort alle zurückbekommen würdest. Das Feld überschreiben darfst du auch nicht, da es sonst in der "alten" Liste nicht mehr stimmt. Es funktioniert also *nicht*, ohne alle Nodes zu kopieren. Ansonsten musst du die Daten und Nodeinfos strikt trennen. Du kannst einen Datencontainer haben, welcher sich in einer Node befindet. Diesen kopierst du in eine neue Node.



ahhhhh... vielen Dank.. jetzt hab ich endlich gerafft warum es nicht funktioniert..
da ist meine Welt doch wieder in Ordnung 
werd ich mir wohl mal was anderes überlegen..
thx


----------



## Shulyn (1. Sep 2009)

Also du willst deine Alte liste in eine Neue Kopieren, jedoch nicht alle Objecte..
Und das ohne die Zeiger zu verbiegen..

Wenn ich dich Richtig verstehe :

 Altliste = a -> b -> c -> d -> e
Neuliste = a -> c -> e

Problem ist das wenn du in der neuen Liste von C auf E verweisen willst, du den Zeiger (next) von C neue setzen müsstest.

Wie wäre es wenn du dir nur die Referenzen auf die gewollten Objecte speicherst?
Im Oberen fall wären das : Head.next / b.next / d.next . Diese wiederrum in eine neue Liste nur das du statt dem Object den object.next speicherst... 
(Oder so ähnlich in der Theorie)


----------



## handoffate (1. Sep 2009)

Shulyn hat gesagt.:


> Also du willst deine Alte liste in eine Neue Kopieren, jedoch nicht alle Objecte..
> Und das ohne die Zeiger zu verbiegen..
> 
> Wenn ich dich Richtig verstehe :
> ...



jop auch eine gute idee.. habe nun einfach die gewollten Objekte in einer ArrayList gespeichert.. tuts auf jeden fall..
nachdem ich endlich verstanden hatte was ich falsch mache war eine akzepzable Lösung nur noch ein Katzensprung


----------



## faetzminator (1. Sep 2009)

Grundsätzlich musst du alle Klassenvariablen ausser [c]next[/c] einfach in ein weiteres Objekt auslagern und eine Instanz dessen in dem Node speichern und zugänglich machen.


----------

