
本文介绍如何通过继承 defaultglazedlistsfilterstrategy 并重写关键方法,实现对 null 值的自动跳过,确保数值列(如“size in bytes”)过滤时不受空值干扰,避免因 null 参与比较导致父行误显等逻辑错误。
本文介绍如何通过继承 defaultglazedlistsfilterstrategy 并重写关键方法,实现对 null 值的自动跳过,确保数值列(如“size in bytes”)过滤时不受空值干扰,避免因 null 参与比较导致父行误显等逻辑错误。
在 NatTable 与 GlazedLists 集成的过滤场景中,DefaultGlazedListsFilterStrategy 默认使用 FilterComparator 对单元格值进行匹配判断。但其底层依赖的 DefaultComparator(或 StringComparator)在遇到 null 时会返回 -1 或 1,而非抛出异常或跳过——这直接导致 null 被错误判定为“满足条件”,尤其在数值范围过滤(如 < 1000)时,null 被视为“小于任何数”,从而意外保留本应被排除的行,进而连带显示其父节点(树形结构下),严重破坏过滤语义。
要彻底规避该问题,不能仅依赖 Comparator.nullsFirst() 或 Comparator.nullsLast() ——它们仅控制 null 的排序位置,无法实现“完全忽略”。正确做法是:自定义一个 FilterStrategy,在 matches() 方法中主动拦截 null 值,使其直接返回 false(即不匹配),从而从源头排除参与比较的可能。
以下是一个生产就绪的实现示例:
public class NullSkippingNumericFilterStrategy<T> extends DefaultGlazedListsFilterStrategy<T> {
public NullSkippingNumericFilterStrategy(
EventList<T> eventList,
IColumnPropertyAccessor<T> columnPropertyAccessor,
List<Integer> filterColumnIndexes) {
super(eventList, columnPropertyAccessor, filterColumnIndexes);
}
@Override
protected boolean matches(T rowObject, int columnIndex, Object filterValue) {
// 获取当前行该列的实际值
Object cellValue = getColumnPropertyAccessor().getPropertyValue(rowObject, columnIndex);
// 关键:若值为 null,直接跳过(不匹配),避免进入 comparator 比较
if (cellValue == null) {
return false;
}
// 若 filterValue 也为 null(极少情况),按需处理;通常 filterValue 非 null
if (filterValue == null) {
return false;
}
// 执行原始匹配逻辑(委托给父类)
return super.matches(rowObject, columnIndex, filterValue);
}
}注册该策略时,需将其注入 FilterRowHeaderComposite 或 FilterRowLayer:
// 假设 columnPropertyAccessor 和 eventList 已就绪
List<Integer> numericColumns = Arrays.asList(2); // 第3列(索引2)为 Size in bytes
NullSkippingNumericFilterStrategy<MyDataType> filterStrategy =
new NullSkippingNumericFilterStrategy<>(eventList, columnPropertyAccessor, numericColumns);
FilterRowLayer<MyDataType> filterRowLayer = new FilterRowLayer<>(
bodyLayerStack,
columnPropertyAccessor,
eventList,
filterStrategy // ← 注册自定义策略
);⚠️ 注意事项:
- 此策略仅影响过滤行为,不影响排序或渲染,因此无需修改 Comparator 或 DisplayConverter;
- 若表中存在多类型数值列(Integer、Long、BigDecimal),建议在 matches() 中增加类型校验与安全转换(如 Number.class.isAssignableFrom(cellValue.getClass())),避免 ClassCastException;
- 对于非数值列(如文本),保留默认行为即可,可扩展策略支持列级开关(通过 filterColumnIndexes 精确控制);
- 树形结构下,因子行 null 被跳过,父行是否显示取决于其自身值是否匹配——这正是预期行为,符合“仅展示真正满足条件的数据”的设计目标。
总结:通过重写 matches() 方法主动拦截 null,比改造 Comparator 更精准、更可控。它将过滤逻辑的语义权交还给业务层——null 不是“最小/最大值”,而是“无意义值”,理应被静默排除。这是 NatTable + GlazedLists 场景下处理稀疏数值数据的推荐实践。

















