✅ 核心挑战
- 类型不安全:直接强转可能抛出
ClassCastException - null 值干扰:
null无法判断类型 - 数字类型混淆:
Integer、Long、Double如何统一处理? - 可维护性差:
if-else堆砌,代码难以扩展
✅ 策略一:使用 instanceof 进行类型过滤(基础但可靠)
需求:从 List<Object> 中提取所有字符串。
实现:
List<Object> mixed = ... // 混合数据
List<String> strings = mixed.stream()
.filter(Objects::nonNull)
.filter(item -> item instanceof String)
.map(item -> (String) item)
.collect(Collectors.toList());✅ 提取所有数字(Integer, Long, Double 等)
List<Number> numbers = mixed.stream()
.filter(Objects::nonNull)
.filter(item -> item instanceof Number)
.map(item -> (Number) item)
.collect(Collectors.toList());✅ Number 是 Integer、Long、Double 等的父类,可统一处理。
✅ 策略二:按“语义类型”分组过滤(高级分类)
需求:将混合数据按“字符串、数字、布尔、其他”分类。
实现:
Map<String, List<Object>> grouped = mixed.stream()
.filter(Objects::nonNull)
.collect(Collectors.groupingBy(item -> {
if (item instanceof String) return "string";
else if (item instanceof Number) return "number";
else if (item instanceof Boolean) return "boolean";
else return "other";
}));
// 使用
List<Object> strings = grouped.get("string");
List<Object> numbers = grouped.get("number");✅ 封装为通用分类器
public enum DataType {
STRING, NUMBER, BOOLEAN, DATE, OTHER;
public static DataType of(Object value) {
if (value == null) return OTHER;
if (value instanceof String) return STRING;
if (value instanceof Number) return NUMBER;
if (value instanceof Boolean) return BOOLEAN;
if (value instanceof LocalDate || value instanceof Instant) return DATE;
return OTHER;
}
}
// 使用
Map<DataType, List<Object>> classified = mixed.stream()
.filter(Objects::nonNull)
.collect(Collectors.groupingBy(DataType::of));✅ 策略三:数字类型的精细化过滤(范围筛选)
需求:从所有数字中筛选出值在 100 ~ 500 之间的项。
实现:
List<Number> filteredNumbers = mixed.stream()
.filter(Objects::nonNull)
.filter(item -> item instanceof Number)
.map(item -> (Number) item)
.filter(num -> {
double value = num.doubleValue(); // 统一转为 double 比较
return value >= 100 && value <= 500;
})
.collect(Collectors.toList());✅ 注意事项:
- 使用
doubleValue()可避免Long超出Integer范围的问题。 - 对精度要求高时,可用
BigDecimal.valueOf(num.doubleValue())。
✅ 策略四:字符串的模式匹配过滤(正则 + 条件)
需求:从字符串中筛选出符合邮箱格式的项。
实现:
Pattern emailPattern = Pattern.compile("\\w+@\\w+\\.\\w+");
List<String> emails = mixed.stream()
.filter(Objects::nonNull)
.filter(item -> item instanceof String)
.map(String::valueOf)
.filter(s -> !s.trim().isEmpty())
.filter(emailPattern.asPredicate())
.collect(Collectors.toList());✅ 扩展:识别并转换数字字符串
// 筛选出能转为整数的字符串
List<Integer> intStrings = mixed.stream()
.filter(Objects::nonNull)
.filter(item -> item instanceof String)
.map(String::valueOf)
.filter(s -> s.matches("\\d+"))
.map(Integer::parseInt)
.collect(Collectors.toList());✅ 策略五:构建类型安全的“过滤管道”(Pipeline)
为了提升可维护性,我们可以构建一个类型过滤管道:
public class ObjectFilterPipeline<T> {
private final List<T> data;
public ObjectFilterPipeline(List<T> data) {
this.data = new ArrayList<>(data);
}
public ObjectFilterPipeline<T> ofType(Class<T> type) {
return new ObjectFilterPipeline<>(
data.stream()
.filter(item -> type.isInstance(item))
.collect(Collectors.toList())
);
}
public ObjectFilterPipeline<String> strings() {
return (ObjectFilterPipeline<String>) ofType(String.class);
}
public ObjectFilterPipeline<Number> numbers() {
return (ObjectFilterPipeline<Number>) ofType(Number.class);
}
public ObjectFilterPipeline<T> where(Predicate<T> condition) {
return new ObjectFilterPipeline<>(
data.stream()
.filter(condition)
.collect(Collectors.toList())
);
}
public List<T> result() {
return new ArrayList<>(data);
}
}✅ 使用方式(流式调用):
List<Object> result = new ObjectFilterPipeline<>(mixedData)
.numbers()
.where(num -> num.doubleValue() > 100)
.result(); // 返回 List<Number>
List<String> emails = new ObjectFilterPipeline<>(mixedData)
.strings()
.where(s -> s.contains("@"))
.result();✅ 优势:链式调用,语义清晰,类型安全(在转换后)。
✅ 5种策略对比速查表
策略 | 适用场景 | 优点 | 缺点 |
instanceof | 基础类型过滤 | 简单直接,性能好 | 重复代码多 |
分组分类 | 数据清洗、统计 | 一次性分类,便于分析 | 内存占用略高 |
数字范围 | 金额、评分、数量筛选 | 精准控制数值条件 | 需统一数值类型 |
正则匹配 | 字符串模式识别 | 灵活,支持复杂规则 | 正则性能开销 |
过滤管道 | 复杂业务逻辑链 | 链式调用,可扩展 | 需要额外封装 |










