Why does my JTable sort an integer column incorrectly?

Viewed 21922

I have a JTable that uses a DefaultTableModel and I allow for sorting when the user clicks on the column headers. However, when the user clicks on a header for a column that has data of type integer it does not sort properly. It seems like it is sorting by String instead of an integer type.

Here is the part of my code where I actually add the data to the table:

        DefaultTableModel aModel = (DefaultTableModel) mainView.logEntryTable.getModel();
                    ResultSetMetaData rsmd;             try {
            mainView.logEntriesTableModel.setRowCount(0);
            rsmd = rs.getMetaData();

            int colNo = rsmd.getColumnCount();
            while(rs.next()){
                Object[] objects = new Object[colNo];
                for(int i=0;i<colNo;i++){
                    objects[i]=rs.getObject(i+1);
                }
                aModel.addRow(objects);
                count++;
            }
            mainView.logEntryTable.setModel(aModel);
            mainView.logEntryTable.getColumnModel().getColumn(0).setMaxWidth(80);

So I tried to override that method and ended up with this:

            @Override
            public Class<?> getColumnClass(int columnIndex){
                if( columnIndex == 0){
                    // Return the column class for the integer column
                }else{
                    // Return the column class like we normally would have if we didn't override this method
                }

                return null;
            }
        };

I've never overridden this before and I'm not quite sure what it is expecting me to do here.

5 Answers

DefaultTableModel returns a column class of Object. As such all comparisons will be done using toString. This may be unnecessarily expensive. If the column only contains one type of value, such as an Integer, you should override getColumnClass and return the appropriate Class. This will dramatically increase the performance of this class.

In this case you should add the snippet code below in your table model:

    @Override
public Class<?> getColumnClass(int columnIndex) {
    if (db.isEmpty()) {
        return Object.class;
    }
    return getValueAt(0, columnIndex).getClass();
}

Most straightforward way I found is to just set the comparator for the specific column. Use it when you already have a TableRowSorter (first line) and set the table to use it (last line).

    TableRowSorter<TableModel> rowSorter = new TableRowSorter<>(tablePanel.getTable().getModel());
    rowSorter.setComparator(1,
            new Comparator<String>() {
                @Override
                public int compare(String o1, String o2) {
                    return Integer.valueOf(o1).compareTo(Integer.valueOf(o2));
                }
            });
    tablePanel.getTable().setRowSorter(rowSorter);
Related