RowFilter.NumberFilter:无法处理“混合”具体数字类型

如果至少有一个值(值= = RowFilter中的值,条目中的值)是小数,则会发生。 这是一个失败的测试:

@Test public void testRowFilterNumberMixCore() { TestEntry entry = new TestEntry(1.2f); RowFilter filter = RowFilter.numberFilter(ComparisonType.AFTER, 1, 0); assertTrue(entry + "must be included " + filter, filter.include(entry)); } 

输出是:

 junit.framework.AssertionFailedError: 
必须包含[entry:1.2] [RowFilter:ComparisonType = AFTER,equivalentValue:1,comparativeClass:class java.lang.Integer]

原因是NumberFilter回退到将数字与它们的数字进行比较.longValue()如果它们不是同一个类(并且可以相互比较)

知道了这个细节,测试失败并不令人惊讶(在后视中,从未想过这是一个问题;-)一个级别的防御是确保 – 在客户端代码中 – 要比较的数字相同的类。 这并不总是可能的(想想fi:tableColumn with columnClass Number)所以我想知道是否/如何改进后备。 就像是:

 if (one instanceof Comparable && one.getClass() == other.getClass()) { // same class, use comparator return ((Comparable) one).compareTo(other); } if (areIntegers(one, other)) { // all integers, use longValue return longCompare(one, other); } if (areDecimals(one, other)) { // anything to do here? } // at last resort convert to BigDecimal and compare those: BigDecimal bigOne = new BigDecimal(one.toString()); BigDecimal bigOther = new BigDecimal(other.toString()); return bigOne.compareTo(bigOther); 

这样做,使测试通过 – 我有点担心隐藏(阅读:未知给我:)陷阱。 任何警告/替代品都非常欢迎!

仅供参考:交叉发布到OTN的Swing论坛

跟进

如上所述实施,现在等待客户投诉 – 在这种情况下会指向所有没有在这里警告我的人:-)

我没有更好的答案,但下面的例子说明了效果。 特别是,基于double原语的RowFilter被装箱为Double ,产生values > 1的预期tableau 。 相比之下,基于float那个被装箱为Float 。 由于类文字不匹配, include()比较long值,意外地过滤所有小values < 2

 import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.util.Arrays; import javax.swing.AbstractAction; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JToggleButton; import javax.swing.RowFilter; import javax.swing.RowFilter.ComparisonType; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableRowSorter; /** @see http://stackoverflow.com/questions/7993546 */ public class FilterTest { private static TableRowSorter sorter; private static RowFilter dFilter; private static RowFilter fFilter; private static boolean b; public static void main(String[] args) { TableModel model = new TableModel(); JTable table = new JTable(model); sorter = new TableRowSorter(model); dFilter = RowFilter.numberFilter(ComparisonType.AFTER, 1d, 0); fFilter = RowFilter.numberFilter(ComparisonType.AFTER, 1f, 0); sorter.setRowFilter(dFilter); table.setRowSorter(sorter); JScrollPane scrollPane = new JScrollPane(table); table.setPreferredScrollableViewportSize(new Dimension(320, 240)); JFrame f = new JFrame("Test"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.add(scrollPane, BorderLayout.CENTER); f.add(new JToggleButton(new AbstractAction("Toggle") { @Override public void actionPerformed(ActionEvent e) { b = !b; if (b) { sorter.setRowFilter(fFilter); } else { sorter.setRowFilter(dFilter); } } }), BorderLayout.SOUTH); f.pack(); f.setVisible(true); } private static class TableModel extends AbstractTableModel { private static final int ROWS = 16; private static final int COLS = 4; private Double[][] matrix = new Double[ROWS][COLS]; public TableModel() { double v = 0; for (Object[] row : matrix) { Arrays.fill(row, Double.valueOf(v += 0.25)); } } @Override public int getRowCount() { return ROWS; } @Override public int getColumnCount() { return COLS; } @Override public Object getValueAt(int row, int col) { return matrix[row][col]; } @Override public Class getColumnClass(int col) { return Number.class; } } } 

只是为了结束这个目标(现在,如果其他答案/评论出现,我们将很乐意重新开启:-) – 如问题中所述解决。

谢谢你的关注!