Nikola
Nikola

Reputation: 2132

JTable fails to sort Integers and Double values properly

I have read several questions about JTable sorting:

Problems with JTable sorting of integer values

JTable + Sorting specific field

but I still can't manage to get it right, for some reason.

I have written this:

String allItemsColumns [] = { "#", "Name", "Stock", 
    "Price", "Type", "Supplier", "Location", "" };
allItemsTableModel = new DefaultTableModel(null, allItemsColumns);
allItemsTable = new JTable(allItemsTableModel)
{       
    Class<?>[] types = { Integer.class, String.class, Integer.class, 
         Double.class, String.class, String.class, String.class, ImageIcon.class };

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        return this.types[columnIndex];
    }
};

but I still get

0
10000
20

when I sort stock. Probably it's an obvious one, but I'm really missing it at the moment.

I do not think it matters how I add info as I (think so that) tell it to read the columns as Integers, Doubles or Strings

My sorting method:

allItemsTable.setAutoCreateRowSorter(true);
TableRowSorter<DefaultTableModel> rowSorter = 
     (TableRowSorter<DefaultTableModel>)allItemsTable.getRowSorter();
rowSorter.setComparator(3, new Comparator<String>() {

    @Override
    public int compare(String o1, String o2)
    {
        return Integer.parseInt(o1) - Integer.parseInt(o2);
    }

});

I have taken it from one of the questions I saw. Column #3 is "Stock" which is Integers only, but the result, like I said is:

0
10000
20

Upvotes: 2

Views: 4380

Answers (2)

kleopatra
kleopatra

Reputation: 51524

To summarize my various comments:

  • TableRowSorter can and does sort Comparable types as expected
  • getColumnClass is the key to provide the sorter with the means of correct sorting as it determines which default Comparator is used
    • if the return type is a Comparable, it's a comparator implementation that delegates to it
    • if the return type is not a Comparable, the Collator instance is used and fed with the value's string representation, no matter whether it's actual type is Comparable or not

So there is no need for a custom comparator in columns containing values that are comparable to each other, just implement the columnClass to return that type and be done.

Here's a snippet demonstrating the behaviour (throw it into you favourite test setup, just any frame will do). First column is defined as Integer which is-a Comparable, second as a Number which !is-a Comparable, others simply Object. All actual values are ints. The first column is sorted numerically, all others by their string representation

final Class[] classes = new Class[]{Integer.class, Number.class};
DefaultTableModel model = new DefaultTableModel(0, 3) {

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        if (columnIndex < classes.length) 
            return classes[columnIndex];
        return super.getColumnClass(columnIndex);
    }

    @Override
    public String getColumnName(int column) {
        return getColumnClass(column).getSimpleName();
    }

};
for (int row = 0; row < 15; row++) {
    model.addRow(new Object[]{row, row, row});
}
JTable table = new JTable(model);
table.setAutoCreateRowSorter(true);

If implementing the columnClass (btw: that should be done in the model, not the view!) appears to not be working in a concrete context, there's some problem elsewhere which should be tracked down (it will hit again sooner or later)

Upvotes: 4

GreyBeardedGeek
GreyBeardedGeek

Reputation: 30088

As far as I know, getColumnClass() has no effect on sorting. It is used for determining editors.

If you are adding string representations of numbers and expecting them to sort numerically, then that's your problem. Add them as numeric types, and it should work. The sort is based on the values in the TableModel implementing the Comparable interface.

Upvotes: 0

Related Questions