# TreeSet mit Objekten befüllen



## ChristianEG (5. Mrz 2010)

Hallo Liebe Community,

ich sitze zurzeit an einer Aufgabe für meinen Porgrammierkurs. Ich muss jetzt ein TreeSet mit einem Objekt befüllen.

Ich habe ein ArrayList mit den Daten die ich benötige. Das Objekt Konto (Kontonummer, Betrag) soll jetzt im TreeSet erzeugt werden. Insgesamt habe ich 42 Datensätze, davon sind einige Konotnummern doppelt, ich sollte am Ende im TreeSet (doppelte Einträge werden ja gelöscht) auf ca. 12 Einträge kommen.

Ich hab das folgendermaßen versucht:


```
protected static TreeSet<Konto> baum = new TreeSet<Konto>();
```

Jetzt habe ich eine Methode erstellt, in dem das TreeSet befüllt werden soll:


```
public static void writeTree() {
		for (int i = 0; i < Buchungsliste.buchungen.size(); i++) {
			System.out.println(i); 
			baum.add(new Konto(Buchungsliste.buchungen.get(i).buch_kontonr, Buchungsliste.buchungen.get(i).buch_betrag));
		}
		
		 Iterator<Konto> iterator;
		 iterator = baum.iterator();
		 
		 while (iterator.hasNext()){
		      System.out.print("Baum " + iterator.next().getKontonr());
		    }
		}
```

Mein Problem: Im TreeSet wird nur 1 Objekt erstellt... und zwar vom ersten Eintrag im ArrayList... die FOR-Schleife wird aber insgesamt 42x initialisiert. Wo liegt mein Fehler? Ich  komme nicht weiter.

Meine Klasse Konto sieht folgend aus:


```
public class Konto implements Comparable<Konto> {

    public String kontonr;
	public String betrag;
	
    
	
    public String getKontonr() {
		return kontonr;
	}

	public void setKontonr(String kontonr) {
		this.kontonr = kontonr;
	}
			
    public String getBetrag() {
		return betrag;
	}

	public void setBetrag(String betrag) {
		this.betrag = betrag;
	}
	
	
	

	public Konto(String KontoNR, String Betrag) {
		this.kontonr = KontoNR;
		this.betrag = Betrag;
    }


	public int compareTo(Konto o) {
		return 0;
	}
	
}
```

Ich glaube es hängt am compareTo. Ich hab viel gegoogelt und in Büchern nachgeschlagen, aber richtig verstehen tue ich es nicht. Deshalb wende ich mich vertrauensvoll an euch Profis, ich selbst bin nur ein blutiger Anfänger. Wäre sehr nett wenn mir jemand helfen könnte, würde mich freuen!

Liebe Grüße aus Wiesbaden,

Christian


----------



## Landei (5. Mrz 2010)

```
baum.add(new Konto(Buchungsliste.buchungen.get(i).buch_kontonr, Buchungsliste.buchungen.get(i).buch_betrag));
```
funktioniert nicht, Maps haben keine add-Methode, sondern die Methode put. Für eine Map musst du einen Schlüssel und einen Wert angeben. Nur die Schlüsselklasse muss sortierbar sein. Etwa so (hier mit der Kontonummer als Schlüssel)

```
baum.put(Buchungsliste.buchungen.get(i).buch_kontonr, new Konto(Buchungsliste.buchungen.get(i).buch_kontonr, Buchungsliste.buchungen.get(i).buch_betrag));
```

Mehr zu Maps unter: Galileo Computing :: Java ist auch eine Insel (8. Auflage) – 12 Datenstrukturen und Algorithmen

Übrigens solltest du hier immer die Fehlermeldung angeben, das ist oft eine wichtige Information, wo es klemmt.


----------



## ChristianEG (5. Mrz 2010)

Hallo,

vielen Dank für deine schnelle Antwort. Ich hatte das mit put auch schon probiert, habe  das Buch zuhause und habe es versucht zu verstehen. Allerdings funktioniert das mit .put bei mir nicht. Eclipse meldet folgendes Problem:


```
The method put(String, Konto) is undefined for the type TreeSet<Konto>
```


----------



## SlaterB (5. Mrz 2010)

ein Set ist keine Map, da gibts keine put-Methode?

was soll es denn jetzt werden, Set oder Map, und was funktioniert dann nicht? 
ich versuche nochmal das erste Post zu lesen 

edit: also put und TreeMap statt TreeSet könnten helfen, am Ende auf die values() zugreifen,
bitte erstmal die Grundfunktionen der Collections kennenlernen


----------



## ChristianEG (5. Mrz 2010)

Ich hab das jetzt nochmal etwas anderst gestaltet. So das ich evtl. einen Fehler finden kann.

Folgendermaßen sieht meine writeTree() Methode jetzt aus:


```
public static void writeTree() {
		for (int i = 0; i < Buchungsliste.buchungen.size(); i++) {
			System.out.println(i); 
			//baum.add(new Konto(Buchungsliste.buchungen.get(i).buch_kontonr, Buchungsliste.buchungen.get(i).buch_betrag));
			baum.add(new Konto(Buchungsliste.buchungen.get(i).buch_kontonr, Buchungsliste.buchungen.get(i).buch_betrag));
			System.out.println(" add " + Buchungsliste.buchungen.get(i).buch_kontonr);
			System.out.println(" add " + Buchungsliste.buchungen.get(i).buch_betrag);
		}
```

Als Ausgabe kommt beim Ausführen jetzt.


```
0
 add 1001
 add 702,78
1
 add 1005
 add -16,27
2
 add 1004
 add -586,08
3
 add 1010
 add -122,77
4
 add 1002
 add 512,54
5
 add 1006
 add 402,14
6
 add 1005
 add -260,17
7
 add 1011
 add -326,56
8
 add 1003
 add 72,72
9
 add 1007
 add 725,4
10
 add 1006
 add 147,93
11
 add 1012
 add -210,2
12
 add 1004
 add 402,93
13
 add 1008
 add 456,45
14
 add 1007
 add 675,08
15
 add 1013
 add 309,31
16
 add 1005
 add 50,27
17
 add 1009
 add -229,8
18
 add 1008
 add 565,09
19
 add 1014
 add -385,81
20
 add 1006
 add 741,68
21
 add 1010
 add 556,15
22
 add 1009
 add 193,04
23
 add 1015
 add -415,02
24
 add 1007
 add 259,8
25
 add 1011
 add -183,35
26
 add 1010
 add 499,39
27
 add 1016
 add 558,65
28
 add 1008
 add -53,59
29
 add 1002
 add -376,34
30
 add 1006
 add -437,45
31
 add 1005
 add -208
32
 add 1011
 add -143,86
33
 add 1003
 add -334,59
34
 add 1007
 add -324,73
35
 add 1006
 add 218,44
36
 add 1012
 add -164,58
37
 add 1004
 add 500,4
38
 add 1008
 add -28,6
39
 add 1007
 add -730,06
40
 add 1013
 add 242,74
41
 add 1005
 add 765,89
```

Das sieht schonmal gut aus. Anscheind fügt er in jedem Schritt einmal Kontonummer und Betrag hinzu. Das ganze insgesamt 42x. Wenn ich aber jetzt den TreeSet ausgeben möchte mit folgender Aufrufung:


```
Iterator<Konto> iterator;
		 iterator = baum.iterator();
		 
		 while (iterator.hasNext()){
             System.out.print("Baum " + iterator.next().getKontonr());
           }
```

Bringt er mir trotzdem  nur den ersten Wert, und zwar 1001. Wieso nicht die restlichen?


EDIT: Ich *muss *leider ein TreeSet verwenden!


----------



## SlaterB (5. Mrz 2010)

gut, bleiben wir beim Set, ist wohl auch besser,

deine compareTo-Methode bewirkt derzeit, dass je zwei Konto-Objekte immer als gleich angesehen werden, 
deshalb wird jedes Element nach dem ersten nicht akzeptiert (add() liefert auch Rückgabewert true/ false)

du musst die compareTo()-Methode so schreiben, dass nur bei wirklich gleichen Daten 0 zurückgegeben wird


----------



## ChristianEG (5. Mrz 2010)

Danke für den Hinweis. Klingt auch logisch.

Ich hab mal versucht das so umzusetzen..


```
public int compareTo(Konto o1) {
		if(this.kontonr == ((Konto) o1).kontonr) {
			return 0;
		} else if (this.kontonr != ((Konto) o1).kontonr){
			return 1;
		} else {
			return -1; 
		}
	}
```

Jetzt werden mir alle Objekte ausgegeben, unsortiert und doppelt. Normalerweise müsste er aber nach einem doppelten Eintrag jetzt ein 0 zurückgeben und diesen nicht hinzufügen?


----------



## Landei (5. Mrz 2010)

Waaaa! Sorry für die Konfusion, ich hatte Map statt Set gelesen! Asche auf mein Haupt...


----------



## SlaterB (5. Mrz 2010)

Strings wenn dann mit equals vergleichen,
aber auch eine schlechte Sortiertung kann Probleme bereiten, immer nur 1 zurückzugeben ohne auf Reihenfolge zu achten kann je nach Einfügereihenfolge dazu führen,
dass "x" links von "y" steht, ein neues "x" aber rechts von "y" eingefügt, weiter links gar nicht mehr geschaut wird

verwende einfach die schon vorhandene compareTo-Methode:
return eigeneKontoNr.compareTo(andereKontoNr);

oder als Konsequenz füge direkt die KontoNummern als String in ein Set, brauchst du wirklich Konto-Objekte mit zufälligen Beträgen dazu?


----------



## ChristianEG (5. Mrz 2010)

```
public int compareTo(Konto o1) {
		if(this.kontonr.equals(((Konto) o1).kontonr)) {
			return 0;
		} else if (!this.kontonr.equals(((Konto) o1).kontonr)) {
			return 1;
		} else {
			return -1; 
		}
	}
```

OK. Habe jetzt das equals Eingebaut. Die Ausgabe reduziert sich auch direkt um 10 Einträge. Ich verstehe allerdings nicht genau was return eigeneKontoNr.compareTo(andereKontoNr); bewirkt und wie ich es einbaue. Könntest du mir das etwas genauer erklären?

Wenn ich das jetzt richtig verstanden habe läuft doch die Abfrage mit dem Vergleich falsch. Sprich: Er vergleicht nicht  mit allen Objekten im TreeSet auf duplikate sondern nur mit dem "Nachbar" ?




> brauchst du wirklich Konto-Objekte mit zufälligen Beträgen dazu?




Sinn ist es, die Buchungen aus der ArrayList in eine Kontoübersicht zu "wandeln". Sprich Konto einmalig ins TreeSet schreiben und bei Duplikaten den Betrag (+/-) dem aktuellen Kontostand zu verrechnen. Am Ende sollten dann alle ~15 Konten im TreeSet mit dem endgültigen Kontostand stehen. Einige Konten haben mehr und andere weniger Buchungen.  Aber zunächst habe ich versucht die Konten überhaupt einmalig anzulegen. Das mit dem verrechnen der Beträge kommt, wenn das oben läuft


----------



## SlaterB (5. Mrz 2010)

return this.kontonr.compareTo(((Konto) o1).kontonr));
liefert eine saubere Sortierung

--------

eine TreeMap vergleicht neue Elemente nicht mit ALLEN vorhandenen,
sondern verwendet einen Sortierbaum, jedes Element wird mit der Wurzel, dessen linken oder rechten Nachfolger usw. verglichen um genau einen Platz zwischen allen anderen zu finden,
wenn dieser Platz schon mit einem gleichen belegt ist, dann kann das Doppelte erkannt und eleminiert werden,

bekommt jedes neue Element dagegen relativ zufällig einen beliebigen Platz, dann kann leicht ein anderes gleiches Element an anderem Platz verfehlt werden, es sind zwei gleiche fälschlicherweise im Set,

wenn du immer nur 1 zurückgibst, lieferst du nicht die Information, ob ein Elemente größer oder kleiner als ein anderes ist,
möglicherweise funktioniert es jetzt auch schon, da immer alle Elemente nach ganz rechts verschoben werden und dabei vielleicht an allen anderen vorbeikommen,
aber schön wär das gewiss nicht

-----

mit dem Verrechen wirst du es aber kaum leichter haben wenn beliebige der Ursprungsbeträge schon gesetzt sind, andere aber nicht,
naja, goldene Wege gibts kaum, kann schon klappen


----------



## ChristianEG (5. Mrz 2010)

Es läuft. Danke dir!

Ich muss mir das mit der TreeMap mal genau anschauen... bin jetzt aber erstmal froh das es funktioniert, jetzt kann ich mich an die Beträge ran machen. Vielen Dank nochmal..


----------



## SlaterB (5. Mrz 2010)

äh ja ich meinte auch das TreeSet, funktionieren eh beide gleich abgesehen davon dass die Map mappt und das Set nicht


----------

