# Function auf Listen



## Jariel (26. Jan 2011)

Diese Main-Methode ist vorgegeben und muss ablaufen:


```
/**
 * Demo fÃ¼r generisches Map
 * 
 * @author jost
 * 
 */
public class Haupt {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// Eine Liste mit Integer Zahlen
		List<Integer> ilist = new MyList<Integer>();
		for (int i = 19; i >= 0; i--) {
			ilist.addFirst(i);
		}
		
		// Eine  simple Funktion, welche eine Zahl auf Ihr Quadrat abbildet.
		Function<Integer, Integer> square = new Square();
		List<Integer> slist = ilist.map(square);
		
		// Ihre Aufgabe: Implementieren Sie die Klasse Vorlesen 
		Function<Integer,String> vorlesen = new Vorlesen();
		List<String> vlist = ilist.map(vorlesen);
		
		System.out.print("Originale Liste:");
		System.out.print(ilist.toString());
		System.out.println();
		
		System.out.print("Liste der Quadrate:");
		System.out.print(slist.toString());
		System.out.println();
		
		System.out.print("Vorgelesen:");
		System.out.print(vlist.toString());
		System.out.println();
		
	}

}
```

Diese 2 Interfaces sind auch noch vorgegeben:


```
/**
 * @author jost
 * 
 * Diese Interface erlaubt es Funktion zu definieren und zu Ã¼bergeben.
 * 
 */
public interface Function<A, B> {
	public B apply(A x);
}
```


```
public interface List<A> {

	/**
	 * @param x
	 *            Element, welches zum neuen Kopf der Liste wird.
	 */
	public void addFirst(A x);

	/**
	 * Entfernt den Kopf der Liste.
	 * 
	 * @return Ehemaliges Kopf-Element
	 */
	public A removeFirst();

	/**
	 * Generiert einen String, welcher die Liste darstellt. Dabei werden die
	 * Elemente der Liste werden durch die von Object geerbten Methode toString
	 * dargestellt.
	 * 
	 * @return String, welcher die Liste vollstÃ¤ndig reprÃ¤sentiert.
	 */
	public String toString();

	/**
	 * Wendet die Funktion fun auf alle Elemente der List an.
	 * @param <B> Diese Funktion ist generisch im Element-Typ der Ergebnisliste
	 * @param fun Eine beliebige Funktion, welche Argumente des Typs A auf Ergebnisse des Typs B abbildet.
	 * @return Die Liste der Bilder.
	 */
	public <B> List<B> map(Function<A, B> fun);
}
```

Und diese Funktion ist vorgegeben:



```
/**
 * Eine simple Funktion, welche eine Zahl auf Ihr Quadrat abbildet.
 * 
 * @author jost
 *
 */
public class Square implements Function<Integer, Integer> {

		@Override
		public Integer apply(Integer i) {
			return i * i;
		}
		
}
```

Ich musste nun eine Klasse "Vorlesen" machen, die das Interface Function implementiert und die einen Integer als String ausgeschrieben zurückgibt. Soll nur für Zahlen zwischen 0 und 19 funktionieren. Aus einem int 1 soll zB. ein String "Eins" werden:


```
public class Vorlesen implements Function<Integer ,String> {

	@Override
	public String apply(Integer x) {

		if(x.equals(0)){
			return "Null";
		}
		if(x.equals(1)){
			return "Eins";
		}
		if(x.equals(2)){
			return "Zwei";
		}
		if(x.equals(3)){
			return "Drei";
		}
		if(x.equals(4)){
			return "Vier";
		}
		if(x.equals(5)){
			return "Fünf";
		}
		if(x.equals(6)){
			return "Sechs";
		}
		if(x.equals(7)){
			return "Sieben";
		}
		if(x.equals(8)){
			return "Acht";
		}
		if(x.equals(9)){
			return "Neun";
		}
		if(x.equals(10)){
			return "Zehn";
		}
		if(x.equals(11)){
			return "Elf";
		}
		if(x.equals(12)){
			return "Zwölf";
		}
		if(x.equals(13)){
			return "Dreizehn";
		}
		if(x.equals(14)){
			return "Vierzehn";
		}
		if(x.equals(15)){
			return "Fünfzehn";
		}
		if(x.equals(16)){
			return "Sechzehn";
		}
		if(x.equals(17)){
			return "Siebzehn";
		}
		if(x.equals(18)){
			return "Achzehn";
		}
		if(x.equals(19)){
			return "Neunzehn";
		}
		else{
			return "blub";
		}
	}

}
```

Ausserdem soll ich eine generische Liste MyList erstellen, die das Interface List implementiert. Besonderheiten ist die Methode toString(), die die Liste als String zurückgibt und die Methode map, die auf die einzelnen Elemente der Liste eine Funktion anwendet und das Ganze in einer neuen Liste speichert:



```
public class MyList<A> implements List<A> {

	private MyListElement<A> first;
	
	 public MyList() {
	      first = null;
	   }

	   public MyList(A r) {
	      first = new MyListElement<A>(r);
	   }	   

	
	@Override
	public void addFirst(A x) {
		 first = new MyListElement<A>(x, first);
		
	}

	@Override
	public A removeFirst() {
		 A result = null;
		   
		 if (first == null) {
			   System.out.println("Warnung: removeFirst auf leere Liste angewandt!");
		   } else {
			   result = first.getValue();
			   first  = first.getNext();
		   }
		   return result;
	   }
	
	public String toString(){
		MyListElement<A> current = first;
		String blub = "";
		   while (current != null) {
		   blub = blub + current.getValue();
			   current = current.getNext();
		   }
		   
		   
		   return blub;
		   
		   }
	

	@Override
	public <B> List<B> map(Function<A, B> fun) {
		MyList<B> k = new MyList<B>();
		MyListElement<A> current = first;
		   while (current != null) {
		   }
		   k.addFirst(fun.apply((A) current.getValue()));;
			   current = current.getNext(); ;
		return k;
	}}
```

Außerdem hab ich noch die Klasse MyListElement geschrieben, für die Elemente der Liste:

[Java]

public class MyListElement<A> {
	private MyListElement<A> next;
	private A value;

	public MyListElement(A r) {
		value = r;
		next = null;
	}

	public MyListElement(A r, MyListElement n) {
		value = r;
		next = n;
	}


	public MyListElement getNext() {
		return next;
	}


	public void setNext(MyListElement next) {
		this.next = next;
	}


	public A getValue() {
		return value;
	}


	public void setValue(A value) {
		this.value = value;
	}

}
[/code]

Wenn ich nun main starte, passiert exakt garnichts... (Keine Fehlermeldung nichts, aber der Computer scheint zu arbeiten als würde er eine Endlosschleife ausführen oder Ähnliches)
Kann sich jemand denken wieso?
(Nur die Klasse Vorlesen, MyList und MyListElement habe ich geschrieben, Rest war vorgegeben)


----------



## SlaterB (26. Jan 2011)

MyList Zeile 51+52 ist Endlosschleife

wie könntest du es herausfinden?
z.B. vor und nach wichtigen Befehlen wie map() Aufrufen in der main() eine System.out.println()-Ausgabe,
dann siehst du beim nächsten Start-Versuch, was noch ausgegeben wird und was vielleicht nicht mehr,
wenn eine schuldige Methode gefunden wurde dann darin weiter verfeinern, natürlich auch schon speziell auf Schleifen achten,

geht schneller als so ein ganzes Post zu schreiben..


----------



## Jariel (26. Jan 2011)

Stimmt danke, ich wunder mich manchmal selbst was für banale Dinge ich überlese, obwohl ich da mindestens 20mal drübergelesen hab...

Hm ok das nächste mal versuche ich mal deinen Ratschlag


----------



## Landei (26. Jan 2011)

Kleiner Verbesserungsvorschlag:

```
public class Vorlesen implements Function<Integer ,String> {

     private static final String[] STRINGS = {"Null","Eins","Zwei"}; //u.s.w;
     
    @Override
    public String apply(Integer x) {
         return STRINGS[x];
    }
}
```


----------

