Mehrere Spalten mit Comparator sortieren

  • Themenstarter Themenstarter Gelöschtes Mitglied 56712
  • Beginndatum Beginndatum
G

Gelöschtes Mitglied 56712

Gast
Guten Tag

mit folgendem Code kann ich EINE Spalte einer JTable (mit model) sortieren.
Java:
    class MyComparator implements Comparator<Object[]> {
        protected boolean isSortAsc;
        protected int isSortCol;

        public MyComparator(boolean sortAsc, int sortCol) {
            isSortAsc = sortAsc;
            isSortCol = sortCol;
        }
        public int compare(Object[] o1, Object[] o2) {
            int result = 0;
            Object test1 = o1[isSortCol];
            Object test2 = o2[isSortCol];
            if (test1 instanceof String) {
                result = ((String)test1).compareTo((String)test2);
            }
            else if (test1 instanceof Integer) {
                try {
                    result = ((Integer)test1).compareTo((Integer)test2);
                } catch (Exception e) {}
            }
            else if (test1 instanceof Double) {
                try {
                    result = ((Double)test1).compareTo((Double)test2);
                } catch (Exception e) {}
            }
            else if (test1 instanceof Date) {
                try {
                    result = ((Date)test1).compareTo((Date)test2);
                } catch (Exception e) {}
            }
            else if (test1 instanceof Boolean) {
                try {
                    result = ((Boolean)test1).compareTo((Boolean)test2);
                } catch (Exception e) {}
            }
            if (!isSortAsc) {
                result = -result;
            }
            return result;
        }
    }
Ausganslage:
Lade aus Datenbank (mySql) mit "SELECT datum, betrag FROM myDB ORDER BY datum, betrag DESC;"
Das funktioniert in der korrekten Sortierung!

Jetzt füge ich eine Zeile (INSERT INTO myDB wurde mit spez. Verschlüsselung ausgeführt) der Tabelle hinzu. Funktioniert auch, aber
sie steht immer am Ende der Tabelle (ohne einsortiert zu werden).

Wenn ich jetzt die Tabelle erst leeren muss und die über 1000 Records mit obigem SELECT neu laden muss, dauert das extrem lange, weil die Daten in der DB-Tabelle speziell verschlüsselt sind und somit erst entschlüsselt werden müssen.
Aber weil die neu erfasste Zeile auch lokal unverschlüsselt vorliegt wollte ich obigen Comparator verwenden um die neue Zeile an der korrekten, sortierten Position anzuzeigen.

Wie, wo, was muss ich erweitern/ergänzen, wenn ich erst die Spalte X (sortCol) und dann innerhalb der Sortierung die Spalte Y (asc oder desc) sortiert haben möchte?
Egal was ich versuche, ich krieg immer nur eine Spalte sortiert. 🙁🙁🙁

Vielen Dank.
 
Zuletzt bearbeitet von einem Moderator:
Comparator'en muss man nicht mehr so kompliziert bauen:
Java:
public static Comparator<Person> createPersonComparator() {
    return Comparator
        .comparing(Person::getName)
        .thenComparing(Person::getAge);
}
Es gibt auch Methoden um 'reverse' zu sortieren oder man dreht das Ergebnis einfach um.

Sinnvollerweise arbeitet man nicht mit Object[], sondern mit sinnvollen Klassen oder Records.
 
Jetzt mal so schnell, schnell ohne IDE hingeschludert:
Java:
    public class TransactionRecord {
        private Date date;
        private double amount;

        public TransactionRecord(Date date, double amount) {
            this.date = date;
            this.amount = amount;
        }

        public Date getDate() {
            return date;
        }

        public double getAmount() {
            return amount;
        }
    }

Java:
import javax.swing.table.AbstractTableModel;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class TransactionTableModel extends AbstractTableModel {

    private static final String[] COLUMN_NAMES = {"Datum", "Betrag"};
    private List<TransactionRecord> data;

    public TransactionTableModel() {
        this.data = new ArrayList<>();
    }

    public void addTransaction(Date date, double amount) {
        data.add(new TransactionRecord(date, amount));
        fireTableDataChanged();
    }

    public void addTransactionRecord(TransactionRecord transactionRecord) {
        data.add(transactionRecord);
        fireTableDataChanged();
    }

    @Override
    public int getRowCount() {
        return data.size();
    }

    @Override
    public int getColumnCount() {
        return COLUMN_NAMES.length;
    }

    @Override
    public String getColumnName(int columnIndex) {
        return COLUMN_NAMES[columnIndex];
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        TransactionRecord record = data.get(rowIndex);
        switch (columnIndex) {
            case 0:
                return record.getDate();
            case 1:
                return record.getAmount();
            default:
                return null;
        }
    }
 
}

Java:
public static Comparator<TransactionRecord> createTransactionRecordComparator() {
    return Comparator
        .comparing(TransactionRecord::getDate).reversed()
        .thenComparing(TransactionRecord::getAmount)
        ...;
}


PS: Date sollte man nicht mehr so wirklich verwenden, s.: LocalDate, LocalDateTime
double ist auch ungünstig, wenn man damit rechnen möchte: It is recommended to use BigDecimal class while dealing with Currency or monetary values as it provides better handling of floating point numbers and their operations. - https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Currency.html
 
Zuletzt bearbeitet:

Neue Themen


Zurück
Oben