Swing DefaultListModel braucht zu lange, um Wert zu setzen

Kweenix

Mitglied
Hallo,
ich schreibe momentan einen Vokabeltrainer.
Er beinhaltet ~6000-7000 Vokabeln. Wenn ich eine Vokabel hinzufüge oder entferne, wird ein DefaultListModel geleert und anschließend werden alle Vokabeln neu sortiert neu hinzugefügt. Doch dies dauert mir zu lange (~15 Sekunden).
Ich habe das einmal mit zwei Instants vor und nach dem Hinzufügen gemessen und mir die Zeit in Nanosekunden ausgeben lassen. Am Anfang braucht jede ~ 50. Vokabel um die 5000000 Nanosekunden. Doch dieser Abstand verändert sich während der foreach Schleife, sodass am Ende jede Vokabel ca. 5000000-11000000 Nanosekunden braucht, um hinzugefügt zu werden. (Das Hinzufügen dauert genau so lange, wenn ich einen leeren String hinzufüge.)
Jetzt möchte ich das gerne vermeiden.
Kann mir dazu jemand helfen?
Dankeschön schonmal😉
Niklas
 
Ja, füge halt einfach nur die neue hinzu oder lösche enterne nur eine alte. Warum soll denn deswegen das Ganze Modell neu erstellt werden?
 
Du kannst es doch gleich an die richtige Stelle einfügen... klar. Da Must du tatsächlich selber die Stelle rausfinden und kannst nicht einfach eine fertig List.sort Routine aufrufen aber manchmal muss man tatsächlich selber Code schreiben als Programmierer....
 
aber manchmal muss man tatsächlich selber Code schreiben als Programmierer....

Ich stimme zu, dass er was Programmieren muss. Aber es muss nicht zwingend das Einfügen an der richtigen Stelle sein. DefaultListModel ist an der Stelle aber auch nicht unbedingt geeignet. Probiere mal:

Java:
import java.util.TreeSet;

import javax.swing.AbstractListModel;

class SortedListModel<T> extends AbstractListModel<T> {
    private TreeSet<T> model;

    public SortedListModel() {
        model = new TreeSet<>();
    }

    @Override
    public int getSize() {
        return model.size();
    }
 
    public void add(T element) {
        if (model.add(element)) {
            int pos = model.headSet(element).size();
            fireContentsChanged(this, pos, pos);
        }
    }

    @Override
    public T getElementAt(int index) {
        return ((T[])model.toArray())[index];
    }
}

Kleiner Tester dazu:
Java:
import java.awt.BorderLayout;

import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTextField;

public class Tester extends JFrame {

    public Tester() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());
     
        SortedListModel<String> model = new SortedListModel<>();
        JList<String> list = new JList<>(model);
        JScrollPane pane = new JScrollPane(list);
     
        add(pane, BorderLayout.CENTER);
     
        JTextField input = new JTextField();
        input.addActionListener(ae -> {
            model.add(input.getText());
            input.setText("");
        });
     
        add(input, BorderLayout.NORTH);
     
        for(int i = 1; i <= 10000; i++) {
            model.add("" + i);
        }
     
        pack();
    }
 
    public static void main(String[] args) {
        new Tester().setVisible(true);
    }
}

Das absolut Schnellste ist es mit 10000 Elementen auch nicht mehr, aber noch weit weg von 15 Sekunden.

Da Must du tatsächlich selber die Stelle rausfinden und kannst nicht einfach eine fertig List.sort Routine aufrufen
Mit einer Ähnlichen Model Implementierung würde auch das theoretisch gehen.
 
Zuletzt bearbeitet:
Und jetzt zeigt man noch das Optimum her:
Java:
class SortedListModel<T extends Comparable<? super T>> extends AbstractListModel<T> {
  private List<T> model = new ArrayList<>();
  
  @Override
  public int getSize() {
    return model.size();
  }
  
  public void add(T element) {
    int index = Collections.binarySearch(model, element);
    int insertionPoint = index < 0 ? -index - 1 : index;
    model.add(insertionPoint, element);
    fireIntervalAdded(this, insertionPoint, insertionPoint);
  }
  
  @Override
  public T getElementAt(int index) {
    return model.get(index);
  }
}
 
Danke erstmal für die vielen Antworten!😀
Ich habe noch ein wenig an dem Code rumgebastelt und jetzt funktioniert es!
Kann mir noch einer erklären, wieso das DefaultListModel meine Aufgabe nicht richtig erledigt. Manchmal erledigt der Computer meine Aufgabe nämlich so schnell, wie ich es will und manchmal dauert es länger(dieselbe Methode). Wäre supii, wenn mir da nochmal wer auf die Sprünge helfen könnte!

P.S.: Ich bin neu hier und wollte wissen, ob man das Thema irgendwie auf gelöst oder so ähnlich stellen kann?
 
Zuletzt bearbeitet:
P.S.: Ich bin neu hier und wollte wissen, ob man das Thema irgendwie auf gelöst oder so ähnlich stellen kann?
Gibts bei der Forensoftware nur als add-on und ist nicht installiert.
Kann mir noch einer erklären, wieso das DefaultListModel meine Aufgabe nicht richtig erledigt. Manchmal erledigt der Computer meine Aufgabe nämlich so schnell, wie ich es will und manchmal dauert es länger(dieselbe Methode). Wäre supii, wenn mir da nochmal wer auf die Sprünge helfen könnte!
Was heißt hier nicht richtig erledigt. Aber wenn du ständig 70000 Einträge löscht, dann hinzufügst, UI updates rausjagst (pro add-OP) und dann noch sortierst, läppert sich das schon an Operationen zusammen.
Du hast auch nicht wirklich gezeigt wie dein Code aussieht, vielleicht ist da auch noch etwas anderes gelaufen.
Zumindest mit meinen Modell hast du immer den gleichen Stock an Grunddaten. Es wird nur jeweils 1 eingefügt (Suchen ist O(log2(n)) und einfügen selbst O(n) - Liegt an der ArrayList) und 1 kleines Update für die UI gesendet.
 

Neue Themen


Zurück
Oben