javaswingenumsjtableabstracttablemodel

Java: order a JTable according to columns from enum


I have a JTable where several columns contain a number from an enums like the following:

public static enum IMPORT_CONF_OPERATION_RESULT {
    OK(0, "OK"),
    ERROR(1, "ERROR"),
    WAITING(2, "WAITING");
    /* ... */
}

So, I needed to override method getValueAt() of table model looping through enum values in order to decode and return the correspondent String for each row as, in the database from which data come from, the numeric values are stored. Now, if the user clicks on the correspondent header column, row are sorted according to numeric values but I would like to order them in alphabetical order. Shall I override sort() method of table model? Isn't looping so many times through enum values to get the description inefficient? Would it slow down table rendering?

UPDATE

This could be a solution following to what STaefi suggested, inside my extended DefaultTableModelField:

@Override
public void sort(int col, boolean ascendest) {
    ColumnProperties columnProperties = this.mapColumn.get(col);
    if (COLUMN_NAME_ENTITY.equals(columnProperties.getInfo()) ||
        COLUMN_OPERATION_TYPE.equals(columnProperties.getInfo()) ||
        COLUMN_OPERATION_RESULT.equals(columnProperties.getInfo()) ||
        COLUMN_ELABORATION_TYPE.equals(columnProperties.getInfo()) ||
        COLUMN_EVENT_STATE.equals(columnProperties.getInfo())) {
        Collections.sort((List<TableImportConfEvent>)this.value, new EnumColumnSorter(ascendest, columnProperties.getInfo()));
        this.fireTableDataChanged();
    }
    else {
        super.sort(col, ascendest);
    }
}

private class EnumColumnSorter implements Comparator<TableImportConfEvent> {

    private int ascending;
    private String columnName;
    public EnumColumnSorter(boolean ascendest, String columnName) {
        this.ascending = ascendest ? 1 : -1;
        this.columnName = columnName;
    }
    @Override
    public int compare(TableImportConfEvent o1, TableImportConfEvent o2) {
        String decodedString1 = "";
        String decodedString2 = "";
        if (COLUMN_NAME_ENTITY.equals(this.columnName)) {
            decodedString1 = getEntityName(o1.getEntityType());
            decodedString2 = getEntityName(o2.getEntityType());
        }
        else if (COLUMN_OPERATION_TYPE.equals(this.columnName)) {
            decodedString1 = getOperationName(o1.getOperationType());
            decodedString2 = getOperationName(o2.getOperationType());
        }
        else if (COLUMN_OPERATION_RESULT.equals(this.columnName)) {
            decodedString1 = getResultName(o1.getOperationResult());
            decodedString2 = getResultName(o2.getOperationResult());
        }
        else if (COLUMN_ELABORATION_TYPE.equals(this.columnName)) {
            decodedString1 = getResultName(o1.getOperationResult());
            decodedString2 = getResultName(o2.getOperationResult());
        }
        else if (COLUMN_EVENT_STATE.equals(this.columnName)) {
            decodedString1 = getStateName(o1.getEventState());
            decodedString2 = getStateName(o2.getEventState());
        }
        return (decodedString1.compareTo(decodedString2)) * this.ascending;
    }   
}

Solution

  • To avoid looping over the enum values for each row, you may want to create a static final HashMap<Integer,IMPORT_CONF_OPERATION_RESULT> to cache the map of values to corresponding labels and initialize it in a static block inside of your enum. Then you can have a public static String getLabelByValue(int value) to use cache and avoid O(n) for looking up the label each time.

    For controlling the sort orders and sort actions you may want to go after TableRowSorter but when you have overriden the getValueAt for your model the default sorting should be sufficient. Other way is use a custom Comparator in your table model to manage the logic of sorting.