... sicher dochWieso sollten sich Schlüssel ständig ändern, das wäre überhaupt nicht gut. Gerade wenn ich Objekte habe, die Schlüssel darstellen, sollen sie sich nicht ändern können. Aber es gibt bestimmt Anwendungsfälle für...
[...] Heraus kam dieses Interface, welches sich seither als recht nützlich erweist.
Eben.Wieso sollten sich Schlüssel ständig ändern, das wäre überhaupt nicht gut. Gerade wenn ich Objekte habe, die Schlüssel darstellen, sollen sie sich nicht ändern können. Aber es gibt bestimmt Anwendungsfälle für...
Das ist keine grosse Sache.Ich würde gerne die Implementierung sehen.
package datatypes.utils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
public class SortableArrayList<E extends Comparable<E>> extends ArrayList<E> implements SortableList<E> {
private static final long serialVersionUID = -8181045362616234380L;
private int sortCount;
public SortableArrayList() {
super();
}
public SortableArrayList(Collection<? extends E> c) {
super(c);
}
public SortableArrayList(int initialCapacity) {
super(initialCapacity);
}
@Override
public int indexOf(Object o) {
sort();
return super.indexOf(o);
}
@Override
public E get(int index) {
sort();
return super.get(index);
}
@Override
public void sort() {
if(isEmpty() || modCount == sortCount) {
return;
}
Collections.sort(this);
sortCount = modCount;
}
@Override
public void sort(Comparator<E> comparator) {
if(isEmpty()) {
return;
}
Collections.sort(this, comparator);
sortCount = modCount - 1;
}
}
@Gregorrr: Also langsam komme ich mir auch etwas vereiert vor...
N einfügen in TreeSet/Map: log(1)+log(2)+..+log(n-1) == log(n)*log(n)/2
Oder täusche ich mich schon wieder?
lg an alle
Sind dir die Methoden "higher(E element)" und "lower(E element)" noch gar nicht aufgefallen? Aufsteigend iteriert man mitaber mal so wie bekommt man aus so nem tree die elemente wieder raus?
find nur first/last aber kein next oder get, etc
da stellt sich mir die frage wie funzt der iterator?
um da was wieder was zu bekommen is der aufwand doch auch n*log(n)
E e = treeSet.first();
while(e != null) {
e = higher(e);
}
E e = treeSet.last();
while(e != null) {
e = lower(e);
}
log(1)+log(2)+..+log(n-1) == log(n)*log(n)/2
"lower()" und "higher()" sind zwei Methoden des TreeSets. Die entsprechenden Methoden der TreeMap wären "lowerKey()" oder "lowerEntry()" bzw. "higherKey()" und "higherEntry()".laut api sind das dann endlosschleifen
denn sie werden wiedergegeben nicht entfernt
und egal welches ich nehm entweder ist das kleinste element root oder das höchste
aber das jeweilige gegenstück sollte doch dann aufwand con log(n) pro zugriff kommen oder?
(bin ein junger entwickler und musste sowas bisher nicht verwenden da meine programme nur wenig datenmengen bearbeiten muss, darum hab ich nicht so die erfahrung mit dem ganzen stuff, ich weis das es da ist wenn es irgendwann mal relevant wird für mich ;D)
halt nun hab ich ich richtig aufgepasst...
wo kommt das lower/higher her?
schwarze magie? D:
verbrennt ihn!
^^ nein bis her nicht
wo kommt das her
sollte nich in der api es irgendwo aufgeführt werden?
public static void treeSet(List<Integer> l) {
long t1 = System.currentTimeMillis();
SortedSet<Integer> s = new TreeSet<Integer>(l);
long t2 = System.currentTimeMillis();
System.out.println("treeSet = " + (t2 - t1));
}
public static void treeMap(List<Integer> l) {
long t1 = System.currentTimeMillis();
SortedMap<Integer, Integer> m = new TreeMap<Integer, Integer>();
for (Integer i : l) {
m.put(i, i);
}
long t2 = System.currentTimeMillis();
System.out.println("treeMap = " + (t2 - t1));
}
public static void hashSet(List<Integer> l) {
long t1 = System.currentTimeMillis();
Set<Integer> s = new HashSet<Integer>();
for (Integer i : l) {
s.add(i);
}
Integer[] ia = new Integer[s.size()];
int i = 0;
for (Integer elem : s) {
ia[i] = elem;
i++;
}
Arrays.sort(ia);
long t2 = System.currentTimeMillis();
System.out.println("hashSet = " + (t2 - t1));
}
public static void hashMap(List<Integer> l) {
long t1 = System.currentTimeMillis();
Map<Integer, Integer> m = new HashMap<Integer, Integer>();
for (Integer i : l) {
m.put(i, i);
}
Integer[][] iaa = new Integer[m.size()][2];
int i = 0;
for (Map.Entry<Integer, Integer> e : m.entrySet()) {
iaa[i][0] = e.getKey();
iaa[i][1] = e.getValue();
i++;
}
Arrays.sort(iaa, new Comparator<Integer[]>() {
public int compare(Integer[] o1, Integer[] o2) {
return o1[0].compareTo(o2[0]);
}
});
long t2 = System.currentTimeMillis();
System.out.println("hashMap = " + (t2 - t1));
}
public static void main(String[] args) {
List<Integer> l = new ArrayList<Integer>();
for (int i = 0; i < 2000000; i++) {
l.add(i);
}
Collections.shuffle(l);
treeSet(l);
treeMap(l);
hashSet(l);
hashMap(l);
}
run:
treeSet = 6271
treeMap = 6911
hashSet = 5023
hashMap = 5788
ERSTELLEN ERFOLGREICH (Gesamtzeit: 0 Minuten 25 Sekunden)
Nein, die HashMap kann O(1) nicht garantieren. Sobald ein Hashcode bereits vorhanden ist und der gleiche noch mal hinzugefügt wird, ist für diese Elemente aus mit O(1), weil nun die HashGruppe per "equals()" durchiteriert wird (Na? Dämmerts? HashCode- und Equals-Konventionen? Hat bei mir auch länger gedauert).Ich bin nur noch nicht sicher, was mit "garantiert" gemeint ist, und ob HashSet(Map) O(1) fürs Einfügen auch garantiert.
Also ich muss mich dann umentscheiden und meine Wahl fällt jetzt auf die erste Antwortmöglichkeit!
PS: Kann jemand das mit der Laufzeit noch einmal aufklären, das wäre super liep von euch!![]()
Komisch... das ist doch die ganze Zeit mein Reden... Die Kopierereien halten beide API-Implementationen "gleichermassen" auf. Gegen Datenhaltung in einer Liste oder einem Array und sortieren, wenn es notwendig ist, ist kein Kraut gewachsen. Ich suche für mein Interface allerdings immer noch nach 'ner akzeptablen Lösung für die Map womit man Keys und Values getrennt ausgeben kann, ohne Key- und/oder Valueset immer neu instanzieren zu müssen. Bisher behelfe ich mir da immer indem ich rigoros über das Entryset iteriere und mir erst in der Schleife das hole, was ich haben wollte, also...Mal abseits der Theorie: Ich habs jetzt 2 Stunden mit einem Mitarbeiter durchgespielt
Für den von mir angenommenen Fall, dass Key/Data-Pärchen ("Entry") in eine sortierte Reihenfolge gebracht werden müssen gilt:
1) ein Sortieren im Bulk ist etwas schneller als das sortierte Einfügen
2) vieles in der Runtime ist eher ein Notnagel als eine sinnvolle Lösung
10.000.000 Elemente mit Schlüssellänge 10 (mittleres Ergebnis über 50 Durchläufe) brauchen mit der TreeMap ca. 38 Sekunden. Bei der Hashmap ist der Zeitkiller das "hintendurchdiebrustinsauge" herauskopieren der Keys und Umwandlung in was "sortierbares" (mit 32 Sekunden aber trotzdem noch schneller). Leider hat man danach "nur" eine sortierte Liste der Keys, man muss also dann über die sortierte Liste lesen uind auf die Hashmap zugreifen was in der Summe die 6 Sekunden Vorsprung etwas auffressen wird.
Soweit die "nimm doch was fertiges"-Lösung durch Aneinanderreihen von API-Aufrufen.
Zerteilt man das etwas und legt die Keys parallel nochmal in einer ArrayList ab dauert der Bulksort nur noch 16 Sekunden weil das umkopieren der Keys aus der HashMap wegfällt.
Ich habe die oben genannte Konstellation mal auf eine alte Routine aus unserer Toolbox losgelassen und die drückt das nochmal auf < 5 Sekunden (ok, die hat beim Füttern aber auch schon nebenbei eine Vorhersage gemacht wo und wie zu sortieren ist).
Fazit: Wenn man es easy haben möchte, dann nimmt man einfach eine TreeMap, Performance ist für den angenommenen Fall nicht mit der Java API zu erreichen, mit wenigen Handgriffen (Abspaltung der Keys) kann man aber eine Halbierung der Laufzeit bekommen.
Bernd
for(Entry<K, V> e : mySortableMap.entrySet()) {
K key = e.getKey();
// oder
V value = e.getValue();
}
Du hast es nie Aufmerksamskeitswirkvoll artikuliert :toll:Komisch... das ist doch die ganze Zeit mein Reden...
Ich suche für mein Interface allerdings immer noch nach 'ner akzeptablen Lösung für die Map womit man Keys und Values getrennt ausgeben kann, ohne Key- und/oder Valueset immer neu instanzieren zu müssen.
Und der Fragesteller hat dazu keine näheren Angaben gemacht.
[...]Ein Beispiel kann z.B. das Zählen von Buchstaben / Zeichen einer Zeichenkette sein und die anschließende Sortierung nach Häufigkeit.
Aber mal ehrlich, der ganze Aufwand für 26 (oder lass es meinetwegen auch 256 sein) Elemente? Das ist sogar mit dem Bubblesort auf einem 10 Jahre alten Handy schneller sortiert als du mit dem Finger schnippen kannst