1Danke
ERLEDIGT
NEIN
NEIN
ANTWORTEN
9
9
ZUGRIFFE
2294
2294
EMPFEHLEN
-
Guten Tag,
hier eine weitere Frage und eine herzliches Danke für Beachtung oder sogar Beantwortung dieser Frage.
Wie kann ich ein TreeSet flexibel und nach verschiedenen Kriterien sortieren?
Sachverhalt:
TreeSet implementiert sortedSet und gilt (daher!?) als sortiert, bzw. sortiert automatisch.
Wenn nun Objekte des Typs Person in ein TreeSet ts sollen, dann muss
die class Person Comparable implementieren.
Sobald mehr als ein einzelnes Objekte des Typ Person in ts hinzugefügt werden soll,
wird die Überschreibung von compareTo(E o) gefordert.
public int compareTo(E o) ist einzige Methode in Comparable.
compareTo(E o) kann sich nur auf EIN Attribut von Person-Objekt beziehen, nämlich das was ich auswähle, denn über die Parameterliste von compareTo(...) ist keine Steuerung möglich.
Wenn ich meine Person Objekte nach jeweils einem anderen Attribut sortieren will
dann geht das in einem Programmlauf und ohne Abändern der compareTo(E o) -Überschreibung wohl nicht.
Wenn ich meine Person Objekte nach jeweils einem anderen Attribut sortieren will,
dann ist TreeSet anscheinend ungeeignet, oder?
Da muss ich vermutlich die Person-Objekte in eine andere Collection (z.B. List ) speichern und jeweils verschiedene Comparatoren
darauf anwenden, oder ?
Viele Grüße
Steve222
-
Nicht ganz, du kannst ja in dem Objekt Person einen SortKey angeben:
Code java:1 2 3 4 5 6 7 8 9 10 11 12 13
/* [...] */ pivate int sortKey = 0; // default sort by first field /* [...] */ @Override public int compareTo(Object o) { Person p = (Person) o; switch(sortKey ){ case 0: { return this.getFirstName().compareTo(p.getFirstName()); } /* [...] */ default: { return this.getFirstName().compareTo(p.getFirstName()); } } } /* [...] */
Musst dann nur noch den Objecten den Sortkey zuweisen, oder aber den Sortkey irgend wo anders her bekommen.
viele Grüße
f.
-
Hallo fassy und
vielen Dank für den schnellen Hinweis.
Dann können nur genau die Person-Instanzen miteinander verglichen und sortiert werden, die den gleichen sort-Key haben.
Aber was, wenn einige Person-Instanzen den einen .sortKey haben und andere Person-Instanzen einen anderen?
Spontan stelle ich es mir mühsam vor, jeder Person-Instanz einen sortkey zuzuweisen und den jedesmal abzuändern
wenn nach einem anderen Merkmal sortiert werden soll.
Code java:1 2 3 4 5 6 7 8
Person objPerson1 = new Person() Person objPerson2 = new Person() Person objPerson3 = new Person() Person objPerson4 = new Person() objPerson1.sortKey = 2; objPerson2.sortKey = 1; objPerson3.sortKey = 2; objPerson4.sortKey = 1;
Oder denke ich verkehrt?
Viele Grüße
Steve222
-
Nachtrag:
Ich denke sortKey darf als private deklariert werden, oder?
-
Nachtrag zu Nachtrag:
Ich wollte miteilen, dass meines Erachtens sortKey NICHT als private deklariert werden darf, sondern
als public oder ggf. protected.
-
Warum solltest du das tun wollen? Ich würde in Java niemals eine Membervariable public deklarieren. Maximal protected und dann auch nur wenn sie in vererbten Klassen weiter genutzt werden soll. Public sollten nur Konstanten sein. 5 Zeilen für einen Getter und nochmal 5 für einen Setter hat man immer über. Wenn du irgendwann mal deine Meinung änderst was den Zugriff auf das Feld angeht musst du nur die Getter und Setter anpassen, nicht jede Klasse die auf das public deklarierte Feld zugreift. Aber das ist eine Glaubens und Design Frage - aber der Zugriff über public direkt auf Objektvariablen ist kein guter Stil und wiederspricht dem OOP Prinzip der DatenKapselung und Abstraktung
Du solltest deine Requirements überdenken. Wann soll sortiert werden? Normalerweise wird beim einfügen in die Map sortiert, d.h. das neue Object wird an die richtige Position geschoben. Das Treeset sortiert nicht automatisch alle anderen Objekte mit um.
Natürlich macht es Sinn nur Objekte mit dem gleichen Sortkey in einem Set zu halten, das ist schließlich der Gedanke hinter einem SortedSet. Ich verstehe halt nicht so ganz was du vorhast, also die Frage ist was möchtest du machen? Wenn du das Set dynamisch umsortieren willst musst du so vorgehen:
1) Sortiere nach Vorname in Set1
2) ändern des sortkeys, also Set1 umsortieren
2.1)alle sortkeys der Object in set1 auf den neuen sortkey setzen
2.2)neue TreeSet anlegen
2.3)alle Objecte in das neue Set schieben
Code java:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
import java.util.Iterator; import java.util.Set; import java.util.TreeSet; public class Test { public static final int SORT_BY_FIRSTNAME = 0; public static final int SORT_BY_LASTNAME = 1; public static void main(String[] args) { Person a = new Person("Klaus", "Heinze"); Person b = new Person("Mara", "Schmidt"); Person c = new Person("Werner", "Meier"); Person d = new Person("Stephanie", "Maier"); Person e = new Person("Ruth", "Mayer"); Person z = new Person("Arno", "Zitter"); z.setSortKey(SORT_BY_LASTNAME); Set<Person> persons = new TreeSet<Person>(); persons.add(a); persons.add(b); persons.add(c); persons.add(d); persons.add(e); System.out.println("SORTED BY FIRSTNAME:"); printSet(persons); /* SORTED BY FIRSTNAME: Klaus Heinze Mara Schmidt Ruth Mayer Stephanie Maier Werner Meier */ persons.add(z); System.out.println("\nSORTED BY FIRSTNAME:"); printSet(persons); /* SORTED BY FIRSTNAME: Klaus Heinze Mara Schmidt Ruth Mayer Stephanie Maier Werner Meier Arno Zitter <-- am Ende eingefügt worden, das sortKey für den Kollegen 1 ist... */ persons = sortSet(persons, SORT_BY_LASTNAME); System.out.println("\nSORTED BY LASTNAME:"); printSet(persons); /* SORTED BY LASTNAME: Klaus Heinze Stephanie Maier Ruth Mayer Werner Meier Mara Schmidt Arno Zitter */ persons = sortSet(persons, SORT_BY_FIRSTNAME); System.out.println("\nSORTED BY FIRSTNAME:"); printSet(persons); /* SORTED BY FIRSTNAME: Arno Zitter Klaus Heinze Mara Schmidt Ruth Mayer Stephanie Maier Werner Meier */ } private static Set<Person> sortSet(Set<Person> set, int sortKey) { Set<Person> newSet = new TreeSet<Person>(); for ( Iterator<Person> i = set.iterator(); i.hasNext();){ Person p = i.next(); p.setSortKey(sortKey); newSet.add(p); } return newSet; } private static void printSet(Set<Person> set){ for (Iterator<Person> i = set.iterator(); i.hasNext();) { Person p = i.next(); System.out.println(p.getFirstName() + " " + p.getLastName()); } } } class Person implements Comparable { private String firstName; private String lastName; private int sortKey = 0; public Person(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } @Override public int compareTo(Object o) { Person p = (Person) o; switch (sortKey) { case 0: { return this.getFirstName().compareTo(p.getFirstName()); } case 1: { return this.getLastName().compareTo(p.getLastName()); } default: { return this.getFirstName().compareTo(p.getFirstName()); } } } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public int getSortKey() { return sortKey; } public void setSortKey(int sortKey) { this.sortKey = sortKey; } }
Die Frage ist und bleibt was du eigentlich vorhast. Du kannst ja auch ein Event/Listener Konzept fahren, d.h. wenn ein sortKey geändert wird triggert das eine Neusortierung. Oder du überschreibst die add Methode des Set und sortierst neu beim Einfügen wenn der sortKey nicht passt. Aber in einem Set nach verschiedenen Keys zu sortieren macht keinen Sinn. Das Set verschieden sortiert ausgeben schon, das kannst du machen wie in meinem Beispiel indem du die sortSet Methode aufrust und dann mit dem nach deinen Wünschen Sortierten Set arbeitest.
Viele Grüße
f.Geändert von fassy (23.01.10 um 01:27 Uhr)
-
Du kannst dem Konstruktor des TreeSet einen Comparator mitgeben. Der funktioniert im Prinzip genauso wie Comparable nur dass er eben zwei zu vergleichende Objekte bekommt. Dadurch kannst du je nach Situation einen anderen Comparator mitgeben und bist nicht darauf angewiesen dass deine Person Comparable ist oder wie Comparable dort implementiert ist.
-
13.04.10 23:14 #8Pretor777 Tutorials.de Gastzugang
Wenn du mit einem TreeSet Strings vergleichst solltest du besser einen Collator (http://java.sun.com/javase/6/docs/ap...lator.html)als comperator verwenden.
-
Für dein Problem hast du dir leider die falsche Programmiersprache ausgesucht; in C# würde ich das Problem folgendermaßen lösen. Ich verwalte die Daten in einem DataSet an, in dem ich die notwendigen Tabellen definiere, füge unter Umständen die notwendigen Indices hinzu, und hole die gewünschten Daten mit Hilfe eines geeigneten SQL-Statements. Als Ergebnis bekomme ich dann ein DataSet, das ich entweder direkt als DataSource einem Anzeigeelement zuweise oder in die benötigten Objekte und Verwaltungsstrukturen umwandle. Dies alles kann man ohne jegliche Datenbankverbindung machen, die Daten bleiben also lokal im Speicher deines Programms.
In Java ist das nicht möglich. Man kann solche Daten in speziellen Bäumen verwalten (B+ Bäume), die man dann allerdings selber implementieren muss. Eine solche Datenstruktur wird bei der Bereichssuche verwendet, die beispielsweise bei graphischen Algorithmen genutzt wird. Die Vorgehensweise ist dann folgendermaßen.
Nehmen wir an, deine Daten sollen nach zwei Kriterien geordent sein, beispielsweise Geburtstag und Name. Auf Ebene 1 (dem Wurzelknoten) unterscheidest du dann nach Geburtstag, ob der Datensatz links oder rechts gespeichert werden soll. Auf Ebene 2 wird dann anhand des Namens unterschieden, ob der Datensatz nach links oder rechts soll. Auf Ebene 3 wird dann wieder per Geburtstag als Kriterium unterschieden etc. Der Comparator müsste also wissen, auf welcher Ebene des Baumes er aufgerufen wird, um das richtige Kriterium zu verwenden, was meines Erachtens nicht möglich ist. Ein TreeSet ist dafür ungeeignet.
Du kannst aber, wie oben erwähnt, einem TreeSet über den Konstruktor einen speziellen Comparator zuweisen. der dann eine spezielle Compare-Methode in deinen Objekten aufruft (z.B. CompareBirthdayAndName(..) ), welche automatisch die richtigen Kriterien verwendet. Die TreeSets fungieren dann quasi als eigene Tabelle mit einem Comparator als einzigem Index. Für jedes TreeSet musst du dann einen eigenen Comparator schreiben und ein spezielle Compare-Funktion in deiner Objektklasse, welche dann von dem jeweiligen Comparator aufgerufen werden kann. Damit das auch sauber funktioniert, musst du zusätzlich für jeden Comparator (welcher jeweils einer eigenen Klasse angehören muss) ein eigenes Interface definieren, das dann von deinen zu sortierenden Objekten implementiert wird, damit diese dann auch von dem Comparator verwendet werden kann. Außerdem musst du als Datentyp für die TreeSets das Interface angeben das verwendet werden soll, nicht die Klasse der Objekte, die darin zu speichern sind. Zudem müssen alle betroffenen TreeSets neu sortiert werden, wenn die Objekte Änderungen in den Daten haben, die für ihre Sortierung relevant sind; eventuell solltest du dafür einen eigenen Event-Mechanismus implementieren. Welche Objekte nach welchem Kriterium sortiert werden sollen und welche nicht, entscheidest du dadurch, welchem TreeSet du sie zuweist.
Alles in allem ist das ziemlich umständlich und aufwändig, aber ich sehe keine andere 'brauchbare' Möglichkeit, dein Problem in Java zu lösen.Geändert von Vereth (16.04.10 um 11:56 Uhr)
Vielen Dank für die Nutzung des Bewerten- und Danke-Buttons
Wenn man sieht, dass man einen anderen glücklich gemacht hat, ist die Welt um zwei glückliche Menschen reicher.
-
Hi,
Du kannst einen Customcomparator bauen, der den jeweiligen Vergleich beherrscht. Umsortieren kannst Du dann mittels Collections.sort().
Beispiel
Code java:1 2 3 4 5 6 7 8 9 10
public static class MyComparator implements Comparator<SetType>, Serializable { public int compare(final SetType o1, final SetType o2) { return null; } } Gerufen wird der dann mittels Collections.sort(meinSet, new MyComparator());
Wenn ich Dich richtig verstanden habe, geht es nur um die Klasse Person, die mehrfach auf unterschiedliche Weise verglichen werden soll, oder? Afaik ist das TreeSet ein sortiertes Set, dass die Reihenfolge nicht mehr ändert. Ein Collections.sort() sollte daher auch im Treeset greifen.
Grüße
goreGeändert von gorefest (16.04.10 um 11:45 Uhr)
Ähnliche Themen
-
NoSuchElementException, TreeSet
Von Steve222 im Forum Java GrundlagenAntworten: 2Letzter Beitrag: 21.01.10, 17:09 -
Objekte in TreeSet einfügen + compareTo
Von MaLb im Forum Algorithmen & Datenstrukturen mit JavaAntworten: 2Letzter Beitrag: 02.06.09, 07:37 -
Treeset mit Objekt (Fehler beim speichern im Treeset)
Von MythosX im Forum JavaAntworten: 3Letzter Beitrag: 02.04.08, 15:10 -
Termine sortieren und im TreeSet speichern
Von hollesepp im Forum Algorithmen & Datenstrukturen mit JavaAntworten: 5Letzter Beitrag: 31.01.08, 15:56 -
Statt HashSet die TreeSet verwenden
Von lernen.2007 im Forum JavaAntworten: 6Letzter Beitrag: 25.11.05, 01:40





Zitieren

Login





