OOP Comparator - Sortierung "optisch" Darstellen

Status
Nicht offen für weitere Antworten.

beginner99

Aktives Mitglied
Hallo,

muss etwa folgende Aufgabe lösen:

Es gibt eine Klasse Personen. Personen haben Vorname, Name, Alter,...

Ich muss jetzt ein GUI machen, dass eine Liste von Personen nach allen dieser Eigenschaften sortieren kann.

-> erledigt
Klasse GUI zum anzeigen
Klasse Personen
Klasse PersonenListe enthält innere statische Klassen vom Tyo comparator plus methoden die den entsprechenden comaprator aufrufen.
Bsp:

Java:
public List<Person> sortByLastName(boolean sortDescending)
    {
        
        Collections.sort(sortedList, new PersonSortByLastName());

        if (sortDescending){
            Collections.reverse(sortedList);
        }

        return sortedList;
    }

Nun soll ich den Sortiervorgang irgendwie "graphisch" darstellen. Als annahme habe ich eine Liste mit 5 Einträgen.
Also beispiel soll die Liste nach jedem Sortierschritt neu angezeigt werden und man kann zb. die Gechwindigkeit per slider einstellen.
Mit einem eigenen Algorithmus wäre dies eher zu verwirklichen. (system pause nach jedem schritt + Listenausgabe).
 
wie Geschwindigkeit ?

d.h. alle 10s soll die liste anders sortiert sein ?

Eine GUI mit einer JList, die deine Personen anzeigt. wenn neu sortiert wurde wird die JList neu erstellt und angezeigt... dann ist die Sortierung in der JList zu sehen
 
da musst du den algo selber schreiben. denn sowas hatten die programmierer wohl nicht vor mit den bereits implementierten methoden
 
was anderes als schnell einen BubbleSort, SelectionSort oder InsertSort schreiben und dann die ausgabe machen, bleibt dir nicht übrig. weil du benutzt ja die sort-Methode der Collection und da bin ich mir zu 110% sicher, dass das nicht geht :rtfm:

du kannst ja dann die Methode compare, wo der Comparator drinne steckt verwenden 😀
 
du kannst dir ja den Source von der API klauen und an den richtigen stellen deine Anweisung für die Darstellung rein pfuschen...

zb
Java:
    public static <T> void sort(List<T> list, Comparator<? super T> c) {
	Object[] a = list.toArray();
	Arrays.sort(a, (Comparator)c);
	ListIterator i = list.listIterator();
	for (int j=0; j<a.length; j++) {
	    i.next();
	    i.set(a[j]);
	}
    }

und aus Arrays dann

Java:
 private static void mergeSort(Object[] src,
				  Object[] dest,
				  int low, int high, int off,
				  Comparator c) {
	int length = high - low;

	// Insertion sort on smallest arrays
	if (length < INSERTIONSORT_THRESHOLD) {
	    for (int i=low; i<high; i++)
		for (int j=i; j>low && c.compare(dest[j-1], dest[j])>0; j--)
		    swap(dest, j, j-1);
	    return;
	}

        // Recursively sort halves of dest into src
        int destLow  = low;
        int destHigh = high;
        low  += off;
        high += off;
        int mid = (low + high) >>> 1;
        mergeSort(dest, src, low, mid, -off, c);
        mergeSort(dest, src, mid, high, -off, c);

        // If list is already sorted, just copy from src to dest.  This is an
        // optimization that results in faster sorts for nearly ordered lists.
        if (c.compare(src[mid-1], src[mid]) <= 0) {
           System.arraycopy(src, low, dest, destLow, length);
           return;
        }

        // Merge sorted halves (now in src) into dest
        for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
            if (q >= high || p < mid && c.compare(src[p], src[q]) <= 0)
                dest[i] = src[p++];
            else
                dest[i] = src[q++];
        }
    }
usw.. aha merge sort, wusste ich gar nicht...
 
Habs jetzt schon ewig rumgespielt, aber kriege das nicht richtig hin. Zum einen ist das Problem wie ich jeden schritt ans GUI gebe, welches dann den momentanen Status anzeigt. Momentan habe ich einfach ein Feld in der sortierklasse wo eine Referenz zum GUi drin ist. Und im GUI eine Funktion die eine eingebene List anzeigen soll.

Die Pause wird auch ausgeführt, aber es ist eher 1 lange Pause und nicht mehrere kurze. Wenn ich debugge und in die gui methode gehe, funktioniert alles korrekt. Im gui zeige ich nur einen String in einer textarea dar. Der string verändert sich wie erwartet mit jedem schritt. Nur wird das im Gui nicht angezeigt.

Java:
    private void mergeSort(Object[] src,
            Object[] dest,
            int low, int high, int off,
            Comparator c) {
        int length = high - low;
        List<Person> temp;
        // Insertion sort on smallest arrays
        if (length < 7) {
            for (int i = low; i < high; i++) {
                for (int j = i; j > low && c.compare(dest[j - 1], dest[j]) > 0; j--) {
                    swap(dest, j, j - 1);
                    temp = Arrays.asList((Person[])dest);
                    gui.displayList(temp);
                    try{
                        Thread.sleep((int)sortDelay * 1000);
                    }
                    catch (InterruptedException ex){
                        ex.printStackTrace();
                    }
                }
            }
            return;
        }

        // Recursively sort halves of dest into src
        int destLow = low;
        int destHigh = high;
        low += off;
        high += off;
        int mid = (low + high) >>> 1;
        mergeSort(dest, src, low, mid, -off, c);
        mergeSort(dest, src, mid, high, -off, c);

        // If list is already sorted, just copy from src to dest.  This is an
        // optimization that results in faster sorts for nearly ordered lists.
        if (c.compare(src[mid - 1], src[mid]) <= 0) {
            System.arraycopy(src, low, dest, destLow, length);
            return;
        }

        // Merge sorted halves (now in src) into dest
        for (int i = destLow, p = low, q = mid; i < destHigh; i++) {
            if (q >= high || p < mid && c.compare(src[p], src[q]) <= 0) {
                dest[i] = src[p++];
            } else {
                dest[i] = src[q++];
            }
        }
    }

EDIT:

Es scheint so als wäre das Gui (JFrame) während der prozedur blockiert. Die Sortierung wird über einen Buttonclick ausgelöst. Auch ein repaint auf den frame oder textarea ändern daran nichts.
 
Zuletzt bearbeitet:
wie wird die Methode aufgerufen? wahrscheinlich vom AWT-Thread aus, der solange blockiert, bis alles fertig ist,
die Aktion muss nebenläufig in einem anderen Thread laufen, z.B.

Runnable r = new Runnable() {
public void run() {
// Code, am besen lesbar nur ein Methodenaufruf
}
}
new Thread(r).start();

siehe auch
http://www.java-forum.org/java-faq-beitraege/7395-progressbars-algorithmen-multithreading.html

Irgendwie habe ich das vermutet. Nur kann ich kaum glauben, dass es nicht auch ohen geht oder anders gesagt, dass ich das völlig anders implementieren muss. Spiele mal ein bisschen rum.
Frage wo gehört der Runnable code hin? Hinter den button click?
 
was ist denn ein Button-Click?, ActionListener? na klar, denn dort gehts ja los,
der Code muss an die richtige Stelle im Ablauf, viel Spielraum hat man nicht
 
was ist denn ein Button-Click?, ActionListener? na klar, denn dort gehts ja los,
der Code muss an die richtige Stelle im Ablauf, viel Spielraum hat man nicht

Also ich bin Programmieranfänger und von Mutlithreading hab ich nicht wirklich Ahnung. Was ich damit sagen will ist, dass ohne igrendein Bsp oder ich ich keine Ahnugn habe wo A und wo Z ist.

Als bsp: Meine Methode braucht ne liste also wie übergebe ich der run mehtode eien Liste?
 
je weniger man weiß, desto mehr Arbeit muss man in Suchen + Lesen stecken,
in meinem Link zur FAQ sind schon paar Beispiele, bei google noch mehr

Variablen kann man mehr oder weniger direkt verwenden, evtl. müssen sie final sein
 
je weniger man weiß, desto mehr Arbeit muss man in Suchen + Lesen stecken,
in meinem Link zur FAQ sind schon paar Beispiele, bei google noch mehr

Variablen kann man mehr oder weniger direkt verwenden, evtl. müssen sie final sein

Bin eher so der Trial & Error Typ ("Praktiker") bin in solchen Sachen.

Hab jetzt das FAQ beispiel angeschaut und irgendwie für mich angepasst. Es scheint zu funktionieren. Nur so ganz verstehe ich nicht, wieso was genau an dem Ort sein muss.
 
falls das keine rhetorische Frage war, solltest du mit Code-Posten 'den Ort' verdeutlichen
 
falls das keine rhetorische Frage war, solltest du mit Code-Posten 'den Ort' verdeutlichen

Das beginnt alleien schon beim button click event bzw actionPreformed:

Java:
    private void btnSortActionPerformed(java.awt.event.ActionEvent evt) {                                        

        new Thread(this).start();

    }

Dann haben wir run. his mit all den if's wäre dann auch ein punkt zu verbessern, momentan ist das ne dropdownliste.

Java:
    public void run() {

        if (cboSortBy.getSelectedItem().equals("Last Name")) {

            txtAreaList.setText(getListString(
                    PersonList.sortByLastName(sortDescending())));

        } else if (cboSortBy.getSelectedItem().equals("First Name")) {
            txtAreaList.setText(getListString(
                    PersonList.sortByFirstName(sortDescending())));

        } else if (cboSortBy.getSelectedItem().equals("Age")) {
            txtAreaList.setText(getListString(
                    PersonList.sortByAge(sortDescending())));

        } else if (cboSortBy.getSelectedItem().equals("Person Number")) {
            txtAreaList.setText(getListString(
                    PersonList.sortByPersonNumber(sortDescending())));

        } 

        JOptionPane.showMessageDialog(this,
                "List sorted.",
                "Success",
                JOptionPane.PLAIN_MESSAGE);

    }

Glaube das dieser code hier hingehört, weil sonst die Sort-Methode im "Event-Thread" abläuft. Oder könnte er auch in actionPerformed stehen?
So funktioniert es auf jedenfall.

Dann wird in der Arrays.mergeSort-Methode aus dem Java API noch folgende Methode aufgerufen (ich habe den source einfach in meien klasse kopiert und entsprechend verändert) an den geigenten Stellen (da wo durch ein Array iteriert wird). Gut, das ist klar, dass dies hier sein muss, ich muss die Anzeige ja nach jedem einzelnen Schritt "erneuern".

Java:
    private void updateDisplay(Object[] arrayToDisplay) {

        final List<Person> temp = Arrays.asList((Person[]) arrayToDisplay);

        try {
            SwingUtilities.invokeAndWait(new Runnable() {

                public void run() {
                    gui.getTextArea().setText(getListString(temp));
                }
            });
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        try {
            // pause per sorting Step
            Thread.sleep(sortDelay * 100);
        } catch (InterruptedException ex) {

            ex.printStackTrace();
        }

    }

Das exception handling ist jetzt auch nicht gerade Ideal...Aber was ist ne InterruptedException bzw wann genau kann die auftreten? Hier hab ich das einfach mal aussen vor gelassen.

Das sortDelay ist noch ne "funtkion" die wir einbauen müssen um die geschwindigkeit des sortierens zu verändern (da steht absichtlich nur 100 und nicht 1000).
 
ja sieht ganz ok aus, bleiben wir bei 'so muss es eben sein', sofern du keine genauere Frage hast

etwas kürzer wäre die run-Methode noch, wenn du den Rückgabewert von
PersonList.sortByLastName(sortDescending()) & Co in einer Variablen speicherst, z.B. x
dann kann das in allen if/ else passieren und erst dahinter kommt

txtAreaList.setText(getListString(x));
 
Status
Nicht offen für weitere Antworten.

Zurück
Oben