# Problem beim schreiben einer eigene generische Klasse LinkedList



## MarioK (20. Apr 2011)

Hallo Gemeinschaft,
Bevor ich zu den Fragen komme, ersteinmal das was mit gegeben wurde und die Aufgabenstellung:

```
public interface List<T> {
/**
* fuegt einen Wert an einem Ende der Liste an
* @param value der einzufuegende Wert
*/
public void add(T value);
/**
* entfernt einen Wert an dem Ende der Liste, an dem auch eingefügt wird
* @return der entfernte Wert bzw. null, wenn Liste leer ist
*/
public T remove();
/**
* stellt fest, ob ein Wert in der Liste enthalten ist (nutzt equals)
* @param value der gesuchte Wert
* @return true g.d.w. value in der Liste enthalten ist
*/
public boolean contains(T value);
/**
* entfernt das erste Vorkommen eines Objektes mit dem übergebenen Wert
* @param value der zu entfernende Wert
* @return der entfernte Wert, wenn vorhanden; sonst: null
*/
public T remove(T value);
/**
* liefert das erste Objektes mit dem übergebenen Wert
* @param value der zu suchende Wert
* @return der gefundene Wert, falls vorhanden; sonst null
*/
public T get(T value);
}
```
Aufgabe: Schreiben Sie eine generische Klasse LinkedList, die dieses List-Interface implementiert. Dabei
soll die Liste in dieser Klasse intern durch eine einfach verkettete Liste realisiert sein.
Außerdem ist die Klasse gründlich zu testen.

So das folgende habe ich bisher gedodet:

```
class LinkedList<T> implements List_I<T> {

	public class Note<T>{
		
		private T element;
		Note<T> next = null;

		public Note(T value){
			this.element = value;
		}	
		public T getElement() {
			return element;
		}
		public void setElement(T element) {
			this.element = element;
		}
		public Note<T> getNext() {
			return next;
		}
		public void setNext(Note<T> next) {
			this.next = next;
		}
		public void debug() {
			System.out.println(((String)element).toString());
			//System.out.println(((String)element).toString() + ": \"" + ((String)element).toString());
		}
		
	}
	
	public Note<T> erster = null;
	public Note<T> letzter = null;
	
	/**
	* fuegt einen Wert an einem Ende der Liste an
	* @param value der einzufuegende Wert
	*/
	@Override
	public void add(T value) {
		
		Note<T> obj = new Note<T>(value);
		
		if(erster == null){		
			obj.next = null;
			erster = obj;
			letzter = obj;					
		}else{		
			letzter.next = obj;
			obj.next = null;
			letzter = obj;		
		}
		
	}
	
	/**
	* entfernt einen Wert an dem Ende der Liste, an dem auch eingefügt wird
	* @return der entfernte Wert bzw. null, wenn Liste leer ist
	*/
	@Override
	public T remove() {
			
		if (erster == null) return null;
		Note<T> obj = erster;
		Note<T> vorrige = null;
		while (obj!=null) {			
			if (obj.next == null){
				letzter = vorrige;
				letzter.next = null;
				return (T) obj;
			}
			vorrige = obj;
			obj = obj.next;			
		}
		return null;
	}

	@Override
	public boolean contains(T value) {

		/**
		* stellt fest, ob ein Wert in der Liste enthalten ist (nutzt equals)
		* @param value der gesuchte Wert
		* @return true g.d.w. value in der Liste enthalten ist
		*/
		
		return false;
	}

	@Override
	public T remove(T value) {

		/**
		* entfernt das erste Vorkommen eines Objektes mit dem übergebenen Wert
		* @param value der zu entfernende Wert
		* @return der entfernte Wert, wenn vorhanden; sonst: null
		*/
		
		return null;
	}

	@Override
	public T get(T value) {
		return value;	
		/**
		* liefert das erste Objekt mit dem übergebenen Wert
		* @param value der zu suchende Wert
		* @return der gefundene Wert, falls vorhanden; sonst null
		*/	
	}
	
	public void gibAlles(){
		Note<T> obj = erster;
		while (obj!=null ) {
			obj.debug();
			obj = obj.next;
		}
		System.out.println();
	}
}
```

mit der passende Main Klasse dazu:

```
public class MainLinkedListTest {

	public static void main(String[] args) {

		//Beginn: wir testen die Methoden auf LinkedList<String>
		LinkedList<String> list = new LinkedList<String>();
		
		System.out.println("---------------------------------------------");
		System.out.println("Beginn Eintraege <String> hinzufuegen. \n");
		System.out.println("Ausgabe nach dem Hinzufuegen:");
		list.add("Testeintrag 1");
		list.add("Testeintrag 2");
		list.add("Testeintrag 3");
		list.add("Testeintrag 4");
		list.add("Testeintrag 2");
		list.add("Testeintrag 1");
		list.gibAlles();
		System.out.println("Ende Eintraege <String> hinzufueger.");
		System.out.println("---------------------------------------------");
		
		System.out.println("---------------------------------------------");
		System.out.println("Beginn letzten Eintrag <String> loeschen. \n");
		System.out.println("Ausgabe vor dem Loeschen:");
		list.gibAlles();
		System.out.println("Ausgabe nach dem Loeschen:");
		list.remove();
		list.gibAlles();
		System.out.println("Ende letzten Eintrag <String> loeschen.");
		System.out.println("--------------------------------------------");
		//Ende: wir testen die Methoden auf LinkedList<String>
		
	}
}
```

Nun zu den Fragen bzw Problem, wo ich bisher noch nicht weiter weiss:
1. Wie muss ich LinkedList verändern, damit ich in der Main auch andere nicht primitive Typen in der LinkedList testen kann? Derzeit kann ich nur String Typen ausgeben. ICh habe dass schon mit Integer getestet, also eine neue LinkedList list1 vom Typ Integer erstellt und Werte hinzugefügt, aber auf der Ausgabe sind nur die list Werte zu sehen. Irgendwie ist die Methode gibAlles in Kombination mit der debug (eigentlich toString) nicht so ganz richtig.
Anmerkung dazu: wenn ich die Methode GibAlles weglasse und stattdessen Sysout(list), eingebe erscheint @7919298d. Das ist ja eine Speicheradresse. Aber ich komme nicht an die Werte.

2. mir erscheint es, als hätte ich in LinkedList ein wenig zu viele VAriablen stehen bzw der Code ist ganz schön aufgebläht. Habt ihr einen Verbesserungsvorschlag, wenn es geht mit Erklärung??

Anmerkung: An den 3 Methoden contains und get arbeite ich derzeit noch, aber die spielen ja zum jetztigen Problem keine Rolle.

Ich wäre euch für eure Hilfe echt dankbar.

Mario


----------



## Landei (20. Apr 2011)

Mit [c] System.out.println(((String)element).toString());[/c] setzt du voraus, dass deine Elemente Strings sind. Warum nicht einfach [c]System.out.println(element);[/c]?


----------



## MarioK (20. Apr 2011)

Landei hat gesagt.:


> Mit [c] System.out.println(((String)element).toString());[/c] setzt du voraus, dass deine Elemente Strings sind. Warum nicht einfach [c]System.out.println(element);[/c]?



mit der Methode gibAlles klappt es jetzt auch mit Integer Werten, aber gibt es da noch ein Tricky, da ich ja die Methode gibAlles nicht gern hätte, also sie soll weg. Siehe dazu Anmerkung zur 1. Frage.


----------



## Crian (20. Apr 2011)

Wofür brauchst du Note<T>? Mir scheint das nicht sinnvoll, da du eh nicht weißt, was T ist, hast du auch nicht mehr als toString() zur Verfügung, weswegen die ganze Subklasse eigentlich überflüssig ist.

Statt der Ausgabe (debug()) würde ich lieber aussagekräftige Tests schreiben.

Edit: Achso du brauchst sie eh für die Verweise auf die Nachbarn.

Edit2: Sicher, dass du eine double linked list erstellen sollst / willst?


----------



## fastjack (20. Apr 2011)

Statt gibAlles würde ich eher einen Iterator oder eine Art travere(Function f) schreiben, außerdem kannst Du toString() überschreiben und eine gängige Listenausgabe erzeugen. toString funktioniert bei allen Objekten, die auch die toString()-Methode überschrieben haben, sonst siehst Du nur die Speicheraddi, da ändert auch der fragwürdige cast nach String nix, das ist sowieso eine potentielle Fehlerquelle. Ansonsten ist Deine Klasse schon auf alle möglichen Typen vorbereitet.

Als Tip: ich würde mir immer den aktuellen Knotenzustand/Zeigerzustand aufmalen, z.B. beim Anfügen, Löschen usw. Dann vergisst man nix.


----------



## MarioK (20. Apr 2011)

fastjack hat gesagt.:


> Statt gibAlles würde ich eher einen Iterator oder eine Art travere(Function f) schreiben, außerdem kannst Du toString() überschreiben und eine gängige Listenausgabe erzeugen. ......
> Als Tip: ich würde mir immer den aktuellen Knotenzustand/Zeigerzustand aufmalen, z.B. beim Anfügen, Löschen usw. Dann vergisst man nix.



ich werde das mit der traverse(Function f) mal probieren.


----------



## MarioK (20. Apr 2011)

Ich schreibe gerade an der contains MEthode aber die will nicht gehen. Wenn ich diese in der Main teste, alias list.contains("bla bla"); kommt keint Fehler, aber es passiert auch nix weiter und der Rechner verlangsamt sich arg. Hier mal der Code:


```
/**
	* stellt fest, ob ein Wert in der Liste enthalten ist (nutzt equals)
	* @param value der gesuchte Wert
	* @return true g.d.w. value in der Liste enthalten ist
	*/
	@Override
	public boolean contains(T value) {

		if (erster == null) return false;
		Note<T> obj = new Note<T>(value);
		Note<T> gesucht = null;
		while (obj!=null) {			
			if( erster.equals(value)) return true;
			if( obj.next.equals(value)) return true;
		}	
		return false;
	}
```


----------



## Crian (21. Apr 2011)

Sieht etwas seltsam aus. So vielleicht?


```
@Override
    public boolean contains(T value) {
         if (erster == null)
            return false;
         if (value == null) /* falls gewünscht */
            return false;

        Note<T> obj = erster;
        while (obj != null) {
            if (value.equals(obj.getElement()))
                return true;
            obj = obj.getNext();
        }   
        return false;
    }
```

Da lässt sich die Abfrage oben ob 
	
	
	
	





```
erster
```


```
null
```
 wird auch noch sparen.


----------



## Landei (21. Apr 2011)

Wieso [c]while[/c]? Ist mit [c]for[/c] doch viel hübscher:


```
@Override
    public boolean contains(T value) {
         if (value == null) /* falls gewünscht */
            return false;
 
        for(Note<T> obj = erster; obj != null; obj = obj.getNext()) {
            if (value.equals(obj.getElement()))
                return true;
        }   
        return false;
    }
```


----------



## MarioK (21. Apr 2011)

@Crian : Danke, jetzt habe ich das auch verstanden und richtig umgesetzt.

zum Nächsten Prob:

```
/**
	* entfernt das erste Vorkommen eines Objektes mit dem übergebenen Wert
	* @param value der zu entfernende Wert
	* @return der entfernte Wert, wenn vorhanden; sonst: null
	*/
	@Override
	public T remove(T value) {
		   
        if (erster == null) return null;
        if (value == null)	return null;
		Note<T> obj = erster;
		Note<T> vorrige = null;
		while (obj!=null) {			
			if (value.equals(obj.getElement())){
				letzter = vorrige;
				letzter.next = null;
				return (T) obj;
			}
			vorrige = obj;
			obj = obj.next;			
		}
		return null;

	}
```

Getestet damit:

```
System.out.println("---------------------------------------------");
		System.out.println("Beginn erstes Vorkommen loeschen. \n");
		System.out.println("Ausgabe vor dem Loeschen:");
		list.gibAlles();
		list.remove("Testeintrag 2");
		System.out.println("Ausgabe nach dem Loeschen:");
		list.gibAlles();
		System.out.println("Ende erstes Vorkommen loeschen.");
		System.out.println("--------------------------------------------");
```

Ausgabe:
Ausgabe vor dem Loeschen:
Testeintrag 1
Testeintrag 2
Testeintrag 3
Testeintrag 4
Testeintrag 2

Ausgabe nach dem Loeschen:
Testeintrag 1

Mhhh ... theoretisch sollte er das erste Vorkommen von "Testeintrag 2" löschen. Statt dessen halt die Ausgabe wie geschrieben. WHY??

Dagegen, wenn ich das erste Vorkommen von "Testeintrag 5" entferne möchte ist die Ausgabe:
Ausgabe nach dem Loeschen:
Testeintrag 1
Testeintrag 2
Testeintrag 3
Testeintrag 4
Testeintrag 2


----------



## MarioK (21. Apr 2011)

Landei hat gesagt.:


> Wieso [c]while[/c]? Ist mit [c]for[/c] doch viel hübscher:
> 
> 
> ```
> ...



wie ist das gemeint  ?? for ist schöner ?? geht es dabei um Geschwindigkeit oder ??


----------



## Landei (21. Apr 2011)

Nein. Bei [c]while[/c] sind wichtige Schleifenelemente (Initialisierung, Weiterzählen) irgendwo verstreut, während sie bei [c]for[/c] einen festen Platz haben. Häufige Fehlerquelle ist, dass das Weiterzählen vergessen wird, oder an der falschen Stelle erfolgt. Weiterhin hat die Schleifenvariable bei [c]while[/c] einen unnötig großen Sichtbarkeitsbereich, was zu Fehlern wie diesem führen kann:


```
Iterator<String> it = getListe().iterator();
while(it.hasNext()){
   System.out.println(it.next());
}

Iterator<String> it2 = getSet().iterator();
while(it2.hasNext()){
   System.out.println(it.next());
}
```

Na, hast du den Fehler gefunden? Solche Bugs können ganz schön Nerven kosten.

Deshalb bevorzuge ich [c]for[/c].


----------



## MarioK (21. Apr 2011)

ich glaube ich verlaufe mich gerade mit dieser Methode hier:

```
/**
	* entfernt das erste Vorkommen eines Objektes mit dem übergebenen Wert
	* @param value der zu entfernende Wert
	* @return der entfernte Wert, wenn vorhanden; sonst: null
	*/
	@Override
	public T remove(T value) {
		   
        if (erster == null) return null;
        if (value == null)	return null;
        Note<T> obj = new Note<T>(value);
		Note<T> vorrige = null;
		while (obj!=null) {			
			if (obj == value){
				obj = obj.next;
				if (vorrige == null) {
					vorrige = obj;
				} else {
					vorrige.next = obj;
				}
				return (T) obj;
			} else {
				vorrige = obj;
		    	obj = obj.next;
		    }		
		}
		return null;

	}
```

Ich möchte doch nur das erste Vorkommen eines Ojektes in der Liste löschen.


----------



## Beni (21. Apr 2011)

Wenn du was aus der Liste entfernst, dann brauchst du garantiert keine neuen Nodes zu erstellen, die Zeile "Note<T> obj = new Note<T>(value);"  scheint extrem falsch zu sein.


----------



## Final_Striker (21. Apr 2011)

MarioK hat gesagt.:


> ich glaube ich verlaufe mich gerade mit dieser Methode hier:



Ja, sehe ich auch so. Denn das was du da geschrieben hast zeigt, dass du keine Ahnung hast, was die Methode überhaupt tun soll.

An deiner Stelle würde ich erst mal mit Papier und Stift anfangen. Eine Liste zeichnen und durchpielen, was bei so einem Löschvorgang überhaupt passiert.


----------



## MarioK (21. Apr 2011)

ok neuer Ansatz. Anmerkung: Zich Blätter liegen schon hier, aber ich mache es wohl zu kompliziert:

```
if (erster == null) return null;
		Note<T> obj = erster;
		Note<T> naechster = null;
		while (obj!=null) {		//durch die list laufen		
			if (obj == value){ 	//wenn 1 Knoten gleich der zu entfernende Wert, dann
				obj = obj.next; //wird dieses obj zum naechsten somit gelöscht
				return (T) obj;	//return gelöschtes Objekt
			}
			naechster = obj;
			obj = obj.next;			
		}
		return null;
```
Aber noch gehts nicht.


----------



## Final_Striker (21. Apr 2011)

Außerdem scheint mir, dass die der Unterschied zwischen einem Knoten und einem Wert nicht klar ist.

[c]if (obj == value){ [/c]

Hier überprüfst du ob eine [c]Node<T>[/c] gleich einem [c]T[/c] ist. Du vergleichst also Äpfel mit Birnen.
In Java kann man nur primitive Datentypen (int, double...) mit == vergleichen. Bei Objekten nutzt man die equals()-Methode


----------



## Crian (21. Apr 2011)

Die einzelnen Elemente der Liste verweisen doch immer auf das nächste (und vielleicht auch auf das vorige, weiß gerade nicht, was du implementiert hast).

Was muss also passieren, wenn du Element i löschen willst?


```
element[i] kann am ende gelöscht werden.

falls es einen Vorgänger gibt:
    element[i-1]->next muss auf element[i]->next zeigen
anderenfalls
    start muss auf element[i]->next zeigen
```

(Wenn du auch nach vorn verweist, ist mehr zu machen.)



----





Landei hat gesagt.:


> Wieso [c]while[/c]? Ist mit [c]for[/c] doch viel hübscher:
> 
> 
> ```
> ...



Stimmt, das ist wirklich hübscher. Es macht das gleiche, ist aber übersichtlicher.


----------



## MarioK (21. Apr 2011)

So jetzt habe ich es soweit das das erste Vorkommen entfernt wird, aber leider auch alle die danach kommen. Ich komme aber jetzt an diesem Punkt nicht mehr weiter ... Please Help ...


```
/**
	* entfernt das erste Vorkommen eines Objektes mit dem übergebenen Wert
	* @param value der zu entfernende Wert
	* @return der entfernte Wert, wenn vorhanden; sonst: null
	*/
	@Override
	public T remove(T value) {
		   
		if (erster == null) return null;
        if (value == null)  return null;
        Note<T> obj = erster;
        Note<T> naechster = null;
        while (obj!=null) {         
            if (value.equals(obj.getElement())){
                letzter = naechster;
                letzter.next = null; ??????????
               
                return (T) obj;
            }
            naechster = obj;
            obj = obj.next;         
        }
        return null;


	}
```


----------



## Crian (21. Apr 2011)

Hast du das oben gelesen?



Crian hat gesagt.:


> Die einzelnen Elemente der Liste verweisen doch immer auf das nächste (und vielleicht auch auf das vorige, weiß gerade nicht, was du implementiert hast).
> 
> Was muss also passieren, wenn du Element i löschen willst?
> 
> ...



Zeichne dir bitte eine Reihe von drei oder vier Objekten und ihre Verweise auf Nachfolger / Vorgänger sowie das erste und letzte Element hin und mal auf, was genau anders werden soll beim Einfügen und beim Löschen. Dann wirst du auch von alleine drauf kommen.


----------



## Final_Striker (21. Apr 2011)

Node->Next

Liste:
A->B, B->C, C->Null

Wir wollen B löschen. Was machen wir? Wir lassen den Next-Zeiger des Vorgängers von B (also A) auf den Nachfolger von B (also C) zeigen.

A->C, C->Null

Somit ist jetzt B gelöscht.


[c]return (T) obj;[/c]
Du willst T haben, gibst aber Node<T> zurück. Nur weil du sagst, der Apfel ist jetzt eine Birne, bleibt es trotzdem ein Apfel.


----------



## MarioK (21. Apr 2011)

Ok mit eure Hilfe bin ich gut voran gekommen. Ich schaffe es jetzt aus der Liste den 2 + Eintrag zu entfernen. Fehlt nur noch die Bedingung, wenn der gesuchte Wert im ersten Objekt ist. Das gibt derzeit noch eine NullPointerExc...


```
/**
	* entfernt das erste Vorkommen eines Objektes mit dem übergebenen Wert
	* @param value der zu entfernende Wert
	* @return der entfernte Wert, wenn vorhanden; sonst: null
	*/
	@Override
	public T remove(T value) {	   		
		if (erster == null) return null;
		Note<T> obj = erster;
		Note<T> vorrige = null;
		while (obj!=null) {			
			if (value.equals(obj.getElement())){
				letzter = vorrige;
				letzter.next = obj.next;		
				return (T) obj;
			}
			vorrige = obj;
			obj = obj.next;			
		}
		return null;
	}
```


----------



## MarioK (21. Apr 2011)

so die Lösung für diese Methode ist auch gefunden ... fehlt nur noch die get Methode ... wenn alles fertig ist poste ich die komplette Lösung ...

Könnte das vielleicht noch jemand eindeutschen :

```
/**
	* liefert das erste Objekt mit dem übergebenen Wert
	* @param value der zu suchende Wert
	* @return der gefundene Wert, falls vorhanden; sonst null
	*/
```


----------



## MarioK (29. Apr 2011)

So hier die zugesagte Komplettlösung. Ist vielleicht noch einfacher zu gestalten, aber dann einmal.


```
package Pflichtaufgabe1;

import java.util.ArrayList;
import java.util.Iterator;


class LinkedList<T> implements List<T> {

	
	@SuppressWarnings("hiding")
	public class Note<T>{
		
		private T element;
		Note<T> next = null;

		public Note(T value){
			this.element = value;
		}	
		public T getElement() {
			return element;
		}
		public void setElement(T element) {
			this.element = element;
		}
		public Note<T> getNext() {
			return next;
		}
		public void setNext(Note<T> next) {
			this.next = next;
		}
		public void debug() {
			System.out.println(element);
		}
		
	}
	
	/**
	* Freiwillige Zusatzaufgabe
	* */
	public class LinkedListIterator implements Iterator<T> {
		ArrayList<T> ls1 = null;
		public LinkedListIterator(LinkedList<T> liste){
			ls1 = new ArrayList<T>();
			Note<T> obj = (Note<T>) erster;
			while (obj!=null ) {
				ls1.add((T) obj);
				obj = obj.next;
			}
		}
		
		public Iterator<T> iterator() {
			return ls1.iterator();
		}
		
		@Override
		public boolean hasNext() {
			return this.hasNext();			
		}

		@Override
		public T next() {
			return this.next();
		}

		@Override
		public void remove() {
			this.remove();
		}
	
	}
	
	public Iterator<T> iterator() {
		LinkedListIterator ll = new LinkedListIterator(this);
		return ll.iterator();
	}
	
	public Note<T> erster = null;
	public Note<T> letzter = null;
	
	/**
	* fuegt einen Wert an einem Ende der Liste an
	* @param value der einzufuegende Wert
	*/
	@Override
	public void add(T value) {	
		Note<T> obj = new Note<T>(value);
		
		if(erster == null){		
			obj.next = null;
			erster = obj;
			letzter = obj;					
		}else{		
			letzter.next = obj;
			obj.next = null;
			letzter = obj;		
		}	
		
	}
	
	/**
	* entfernt einen Wert an dem Ende der Liste, an dem auch eingefügt wird
	* @return der entfernte Wert bzw. null, wenn Liste leer ist
	*/

	@Override
	public T remove() {
			
		if (erster == null) return null;
		Note<T> obj = erster;
		Note<T> vorrige = null;
		while (obj!=null) {			
			if (obj.next == null){
				letzter = vorrige;
				letzter.next = null;
				return obj.element;
			}
			vorrige = obj;
			obj = obj.next;			
		}
		return null;
		
	}
	
	/**
	* stellt fest, ob ein Wert in der Liste enthalten ist (nutzt equals)
	* @param value der gesuchte Wert
	* @return true g.d.w. value in der Liste enthalten ist
	*/
	@Override
	public boolean contains(T value) {

		if (erster == null)return false;
        if (value == null) return false;

        Note<T> obj = erster;
        while (obj != null) {
            if (value.equals(obj.getElement()))
                return true;
            obj = obj.getNext();
        }   
        return false;
        
	}
	
	/**
	* entfernt das erste Vorkommen eines Objektes mit dem übergebenen Wert
	* @param value der zu entfernende Wert
	* @return der entfernte Wert, wenn vorhanden; sonst: null
	*/

	@Override
	public T remove(T value) {
		
		//Liste leer return null
		if (erster == null) return null;
		//übergebener Wert null return null
		if (value == null) return null;
		Note<T> obj = erster;
		Note<T> vorrige = null;
		while (obj!=null) {			
			if (value.equals(obj.getElement())){
				if (vorrige == null){
					erster = obj.next;
				} else {
					letzter = vorrige;
					letzter.next = obj.next;		
					return obj.element;
				}
			}
			vorrige = obj;
			obj = obj.next;			
		}
		return null;
		
	}
	
	/**
	* liefert das erste Objekt mit dem übergebenen Wert
	* @param value der zu suchende Wert
	* @return der gefundene Wert, falls vorhanden; sonst null
	*/	
	@Override
	public T get(T value) {
		
		if (erster == null) return null;
		if (value == null) return null;
		Note<T> obj = erster;
		while (obj != null) {
			if(value.equals(obj.getElement())){
				return obj.element;
			}
			obj = obj.next;
		
		
		}
		return null;
	}

	/**
	* Methode zur Ausgabe der LinkedList
	* in der Main
	*/	
	public void gibAlles(){
		
		Note<T> obj = erster;
		while (obj!=null ) {
			obj.debug();
			obj = obj.next;
		}
		System.out.println();
		
	}
}
```


----------



## Landei (30. Apr 2011)

Node wie "Knoten" schreibt sich übrigens mit "d". Zuviel Deathnote geschaut?

Ob deine Lösung korrekt ist, kann ich so nicht sagen, aber ich rate dringend dazu, eine Testklasse dafür zu schreiben. Wenn du NetBeans oder Eclipse hast, kannst du dir ein Skelett für einen Unit-Test generieren lassen...


----------



## MarioK (30. Apr 2011)

Landei hat gesagt.:


> Node wie "Knoten" schreibt sich übrigens mit "d". Zuviel Deathnote geschaut?
> 
> Ob deine Lösung korrekt ist, kann ich so nicht sagen, aber ich rate dringend dazu, eine Testklasse dafür zu schreiben. Wenn du NetBeans oder Eclipse hast, kannst du dir ein Skelett für einen Unit-Test generieren lassen...



Danke Landei, aber ich schreibe Note mit Absicht so ...

ich hatte  doch am Anfang des Threads schon eine Testklasse abgelichtet ... sollte die doch ausreichen ???


----------



## Landei (30. Apr 2011)

Soweit sich das sehe, verwendest du dort nur add, remove und gibAlles. Was ist mit get, contains und dem Iterator? Und funktioniert remove auch bis die Liste leer ist?


----------



## MarioK (30. Apr 2011)

Ooops sorry hatte ich nicht aktuallisiert ...

```
package Pflichtaufgabe1;

/**
 * Diese Klasse testet die  generische Klasse LinkedList,
 * 
 */
public class MainLinkedListTest {

	public static void main(String[] args) {

		//Beginn: wir testen die Methoden auf LinkedList<String>
		
		LinkedList<String> list = new LinkedList<String>();
		
		System.out.println("---------------------------------------------");
		System.out.println("Beginn Eintraege <String> hinzufuegen. \n");
		System.out.println("Ausgabe nach dem Hinzufuegen:");
		list.add("Testeintrag 1");
		list.add("Testeintrag 2");
		list.add("Testeintrag 3");
		list.add("Testeintrag 4");
		list.add("Testeintrag 5");
		list.add("Testeintrag 1");
		list.gibAlles();
		System.out.println("Ende Eintraege <String> hinzufueger.");
		System.out.println("---------------------------------------------");
		
		System.out.println("---------------------------------------------");
		System.out.println("Beginn letzten Eintrag <String> loeschen. \n");
		System.out.println("Ausgabe vor dem Loeschen:");
		list.gibAlles();
		System.out.println("Ausgabe nach dem Loeschen:");
		list.remove();
		list.gibAlles();
		System.out.println("Ende letzten Eintrag <String> loeschen.");
		System.out.println("--------------------------------------------");
		
		System.out.println("---------------------------------------------");
		System.out.println("Beginn contains auf Liste <String>. \n");
		if (list.contains("Testeintrag 2")){
			System.out.println("Testeintrag 2 ist in der Liste vorhanden. \n");;
		} else {
			System.out.println("Testeintrag 2 ist nicht in der Liste vorhanden. \n");
		}
		if (list.contains("Testeintrag 55")){
			System.out.println("Testeintrag 55 ist in der Liste vorhanden. \n");;
		} else {
			System.out.println("Testeintrag 55 ist nicht in der Liste vorhanden. \n");
		}
		System.out.println("Ende contains auf Liste <String>.");
		System.out.println("--------------------------------------------");

		
		System.out.println("---------------------------------------------");
		System.out.println("Beginn erstes Vorkommen loeschen. \n");
		System.out.println("Ausgabe vor dem Loeschen:");
		list.gibAlles();
		list.remove("Testeintrag 3");
		System.out.println("Ausgabe nach dem Loeschen:");
		list.gibAlles();
		System.out.println("Ende erstes Vorkommen loeschen.");
		System.out.println("--------------------------------------------");
		
		System.out.println("---------------------------------------------");
		System.out.println("Beginn get Methode testen <String>. \n");
		System.out.println(list.get("Testeintrag 4") + "	:Testeintrag 4 ist in der Liste vorhanden.");
		System.out.println(list.get("Testeintrag 555") + "  :Testeintrag 555 ist nicht in der Liste vorhanden" + "\n");
		System.out.println("Zum Vergleich die LinkedList list: \n");
		list.gibAlles();
		System.out.println("Ende get Methode testen <String>.");
		System.out.println("--------------------------------------------");
		
		//Ende: wir testen die Methoden auf LinkedList<String>
		
		//Beginn: wir testen die Methoden auf LinkedList<Integer>
		
		LinkedList<Integer> list1 = new LinkedList<Integer>();
		
		System.out.println("---------------------------------------------");
		System.out.println("Beginn Eintraege <Integer> hinzufuegen. \n");
		System.out.println("Ausgabe nach dem Hinzufuegen:");
		list1.add(2);
		list1.add(3);
		list1.add(4);
		list1.add(2);
		list1.add(1);
		list1.gibAlles();
		System.out.println("Ende Eintraege <Integer> hinzufueger.");
		System.out.println("---------------------------------------------");
		
		System.out.println("---------------------------------------------");
		System.out.println("Beginn letzten Eintrag <Integer> loeschen. \n");
		System.out.println("Ausgabe vor dem Loeschen:");
		list1.gibAlles();
		System.out.println("Ausgabe nach dem Loeschen:");
		list1.remove();
		list1.gibAlles();
		System.out.println("Ende letzten Eintrag <Integer> loeschen.");
		System.out.println("--------------------------------------------");
		
		System.out.println("---------------------------------------------");
		System.out.println("Beginn contains auf Liste <Integer>. \n");
		if (list1.contains(2)){
			System.out.println("2 ist in der Liste vorhanden. \n");;
		} else {
			System.out.println("2 ist nicht in der Liste vorhanden. \n");
		}
		if (list1.contains(444)){
			System.out.println("444 ist in der Liste vorhanden. \n");;
		} else {
			System.out.println("444 ist nicht in der Liste vorhanden. \n");
		}
		System.out.println("Ende contains auf Liste <Integer>.");
		System.out.println("--------------------------------------------");
		
		System.out.println("---------------------------------------------");
		System.out.println("Beginn erstes Vorkommen loeschen. \n");
		System.out.println("Ausgabe vor dem Loeschen:");
		list1.gibAlles();
		list1.remove(4);
		System.out.println("Ausgabe nach dem Loeschen:");
		list1.gibAlles();
		System.out.println("Ende erstes Vorkommen loeschen.");
		System.out.println("--------------------------------------------");
		
		System.out.println("---------------------------------------------");
		System.out.println("Beginn get Methode testen <String>. \n");
		System.out.println(list1.get(7) + "		:7 ist nicht in der Liste.");
		System.out.println(list1.get(3) + "		:3 ist in der Liste");
		System.out.println(list1.get(4) + "		:4 ist nicht in der Liste" + "\n");
		System.out.println("Zum Vergleicht die LinkedList list1:");
		list1.gibAlles();
		System.out.println("Ende get Methode testen <String>.");
		System.out.println("--------------------------------------------");
		
		//Ende: wir testen die Methoden auf LinkedList<Integer>
	}
}
```


----------



## Landei (30. Apr 2011)

Cool, das sieht besser aus.


----------



## MarioK (19. Mai 2011)

ich versuche gerade die Methode GibAlles und debug zu ersetzen durch eine toString MEhtode, aber dann kommt folgendes Problem:
Erstmal das was ich geschrieben habe:

```
public class Note{
		
		private T element;
		Note next = null;

		...........
		public String toString(){
			return element.toString();	
		}
		
	}
```


```
@Override
	public String toString(){
		StringBuilder sb = new StringBuilder();
		Note obj = erster;
		while(obj != null){
			sb.append(obj.toString());
			sb.append(",");
		}
		return sb.toString();
	}
```

Bekomme folgenden Fehler wenn ich die Liste wie folgt aufrufen möchte sysout(list);


```
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at java.util.Arrays.copyOf(Unknown Source)
	at java.lang.AbstractStringBuilder.expandCapacity(Unknown Source)
	at java.lang.AbstractStringBuilder.append(Unknown Source)
	at java.lang.StringBuilder.append(Unknown Source)
	at Pflichtaufgabe2.LinkedList.toString(LinkedList.java:233)
	at java.lang.String.valueOf(Unknown Source)
	at java.io.PrintStream.println(Unknown Source)
	at Pflichtaufgabe2.MainLinkedListTest.main(MainLinkedListTest.java:25)
```


----------



## MarioK (19. Mai 2011)

Lösung selbst gefunden :

```
@Override
	public String toString(){
		StringBuilder sb = new StringBuilder();
		Note obj = erster;
		while(obj != null){
			sb.append(obj.toString());
			obj = obj.next;
			sb.append(",");
		}
		return sb.toString();
	}
```


----------



## Landei (19. Mai 2011)

Sieht so aus, also ob [c]while(obj != null)[/c] immer erfüllt würde und so der Stringbuilder immer größer wird bis der Speicher volläuft. Woran das wohl liegen könnte?


----------



## MarioK (19. Mai 2011)

Aber bei diesen Problem komme ich nicht weiter :

```
/**
	* entfernt das erste Vorkommen eines Objektes mit dem übergebenen Wert
	* @param value der zu entfernende Wert
	* @return der entfernte Wert, wenn vorhanden; sonst: null
	*/

	@Override
	public T remove(T value) {
		
		//Liste leer return null
		if (erster == null) return null;
		//übergebener Wert null return null
		if (value == null) return null;
		Note obj = erster;
		Note vorrige = null;
		while (obj!=null) {			
			if (value.equals(obj.getElement())){
				if (vorrige == null){
					erster = obj.next;
				} else {
					letzter = vorrige;
					letzter.next = obj.next;
					return obj.element;
				}
			}
			vorrige = obj;
			obj = obj.next;			
		}
		return null;
		
	}
```

Diese Methode soll ja nur das erste Vorkommen löschen. Wenn Beispeilsweise meine Liste folgendes beinhaltet : 2,3,4,2,1 und ich 2 löschen will kommt bei meiner Methode folgendes bei raus : 3,4,1, d.h. er löscht alle 2 aus der Liste. Why ??


----------



## MarioK (19. Mai 2011)

Landei hat gesagt.:


> Sieht so aus, also ob [c]while(obj != null)[/c] immer erfüllt würde und so der Stringbuilder immer größer wird bis der Speicher volläuft. Woran das wohl liegen könnte?



Danke für die Antwort, aber ich hatte die Lösung schon gefunden : obj = obj.next; fehlte noch ...


----------



## MarioK (19. Mai 2011)

so wieder Problem selbst gelöst ... jetzt löscht remove auch wirklich nur das erste Vorkommen in der List....

```
@Override
	public T remove(T value) {
		
		//Liste leer return null
		if (erster == null) return null;
		//übergebener Wert null return null
		if (value == null) return null;
		Note obj = erster;
		Note vorrige = null;
		int count = 0;
		while (obj!=null && count == 0) {
			if (value.equals(obj.getElement())){
				if (vorrige == null){
					erster = obj.next;
				} else {
					letzter = vorrige;
					letzter.next = obj.next;
					return obj.element;
				}
				count ++;
			}
			vorrige = obj;
			obj = obj.next;			
		}
		return null;
		
	}
```


----------

