如何用Java泛型合并Spring Boot中两个CsvToBeanFilter实现类?
用Java泛型合并CsvToBeanFilter实现的方案
你完全可以用一个泛型类替代两个重复实现,核心是把类型转换逻辑和过滤逻辑解耦,让泛型参数适配不同的数据类型。不需要抽象类,直接一个泛型实现类就能搞定,代码复用性更高。
实现思路
- 泛型类
GenericContainsFilter<T>实现CsvToBeanFilter,泛型T表示要匹配的目标数据类型(Integer/String等) - 类内维护三个核心属性:
- 要检查的CSV列索引
- 目标匹配列表(
List<T>) - 类型转换器(
Function<String, T>):负责把CSV读取到的字符串转成目标类型T
- 在
allowLine方法里,统一执行「取列值→转类型→判断是否在目标列表」的逻辑
完整代码实现
import com.opencsv.bean.CsvToBeanFilter; import java.util.List; import java.util.function.Function; public class GenericContainsFilter<T> implements CsvToBeanFilter { private final int targetIndex; private final List<T> targetList; private final Function<String, T> typeConverter; // 构造方法,接收核心参数 public GenericContainsFilter(int targetIndex, List<T> targetList, Function<String, T> typeConverter) { this.targetIndex = targetIndex; this.targetList = targetList; this.typeConverter = typeConverter; } @Override public boolean allowLine(String[] line) { // 边界校验:索引越界直接返回false(可根据业务调整) if (targetIndex < 0 || targetIndex >= line.length) { return false; } try { // 转换CSV字符串为目标类型,判断是否在列表中 T value = typeConverter.apply(line[targetIndex]); return targetList.contains(value); } catch (Exception e) { // 类型转换失败时的处理,比如返回false或抛出异常,按需调整 return false; } } // 静态工厂方法,简化常用类型的实例创建(可选,但更易用) public static GenericContainsFilter<Integer> forInteger(int index, List<Integer> targetList) { return new GenericContainsFilter<>(index, targetList, Integer::valueOf); } public static GenericContainsFilter<String> forString(int index, List<String> targetList) { // String类型不需要转换,直接返回原字符串 return new GenericContainsFilter<>(index, targetList, s -> s); } }
使用示例
// 替代原ContainsIntegerFilter的用法 List<Integer> integerTargets = List.of(100, 200, 300); GenericContainsFilter<Integer> integerFilter = GenericContainsFilter.forInteger(2, integerTargets); // 替代原ContainsStringFilter的用法 List<String> stringTargets = List.of("admin", "user", "guest"); GenericContainsFilter<String> stringFilter = GenericContainsFilter.forString(0, stringTargets);
为什么不需要抽象类?
你的抽象类方案可能会引入不必要的层级,因为这里的差异仅在于类型转换逻辑,核心过滤逻辑完全一致。用泛型+函数式接口(Function)已经足够把差异点抽离,代码更简洁,复用性更强。如果后续需要支持其他类型(比如Long、Double),只需要新增对应的静态工厂方法,或者直接传入自定义转换器即可。
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

