【问题标题】:RowFilter.NumberFilter: can't handle "mixed" concrete number typesRowFilter.NumberFilter:无法处理“混合”具体数字类型
【发布时间】:2011-11-03 10:45:20
【问题描述】:

如果至少有一个值(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, compatibleValue: 1, compatibleClass: class java.lang.Integer]

原因是 NumberFilter 回退到通过它们的 number.longValue() 比较数字,如果它们不是同一个类(并且可以相互比较)

知道这个细节,测试失败并不令人惊讶(事后看来,不会想到这是一个问题 ;-) 一个级别的防御是确保 - 在客户端代码中 - 要比较的数字 是同一类。这并不总是可能的(想想 f.i.: a 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's Swing forum

跟进

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

【问题讨论】:

  • 我可以看到 ???? stackoverflow.com/questions/6187566/… ???与否
  • @mKorbel - 感谢您的链接。如果我正确理解了这个问题,看起来有点不相关:如果列类与 getColumnClass 中保证的类不同,格式化程序就会吠叫。我认为这非常值得期待。这归结为简单的数字比较,仅在背景中的表格(自然是明显的目标区域之一:-)

标签: java swing numbers compare rowfilter


【解决方案1】:

我没有更好的答案,但下面的示例说明了效果。特别是,基于double 原语的RowFilterboxed 作为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<TableModel> sorter;
    private static RowFilter<TableModel, Integer> dFilter;
    private static RowFilter<TableModel, Integer> fFilter;
    private static boolean b;

    public static void main(String[] args) {
        TableModel model = new TableModel();
        JTable table = new JTable(model);
        sorter = new TableRowSorter<TableModel>(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;
        }
    }
}

【讨论】:

  • 是的,这是客户的客户检测到的效果顺便说一句,与是否装箱无关,只是为了澄清。感谢您的 sscce!
猜你喜欢
  • 2018-03-06
  • 2016-03-17
  • 2017-06-06
  • 2018-05-23
  • 1970-01-01
  • 2022-11-11
  • 2022-08-14
  • 2021-12-15
  • 2018-08-26
相关资源
最近更新 更多