如果至少有一个值(值= = 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] must be included [RowFilter: ComparisonType = AFTER, comparableValue: 1, comparableClass: class java.lang.Integer]
原因是NumberFilter回退到将数字与它们的数字进行比较.longValue()如果它们不是同一个类(并且相互比较)
知道细节,测试失败并不令人惊讶(在后视中,从未想过这是一个问题;-)一个级别的防御是确保 - 在客户端代码中 - 要比较的数字< em>是同一类的。这并不总是可能的(想想f.i: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
后续
如上所述实施,现在正在等待客户投诉 - 在这种情况下会指向所有没有在此警告我的人:-)
答案 0 :(得分:4)
我没有更好的答案,但下面的例子说明了效果。特别是,基于RowFilter
基元的double
boxed为Double
,生成具有values > 1
的预期画面。相反,基于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;
}
}
}