Java Stream过滤对象报NPE问题修复及筛选规则实现
问题原因
当前代码抛出空指针、逻辑不符合预期的核心问题如下:
- 筛选逻辑写了两个串行的
filter,是必须同时满足的与关系:第一个filter只保留objId == null的对象,第二个filter直接对null值调用contains方法,必然触发空指针;完全没有实现“满足任意一个条件即可保留”的或逻辑 - 直接用字符串
contains方法做匹配会出现误判:比如objId值为"7,84,3"、sections包含"8"时,会错误匹配到"84"中的子串"8",不符合拆分后元素精确比对的要求 getData方法的测试数据赋值顺序错误:给objs1设置"1,2,3"加入列表后,又重新给objs1赋值"4,5,6"再加入objs2,导致objs2、objs3的objId属性根本没有被赋值,默认是null,测试数据本身不符合预期- 没有覆盖
sections为null/空串的边界场景,不满足定义的场景4规则
修正后代码
修正点包括:
- 整合筛选逻辑为单个filter,实现空objId直接保留、非空objId做拆分后精确交集匹配的或逻辑
- 所有字符串拆分后做元素精确相等判断,避免子串误匹配
- 增加sections空值兜底逻辑,符合边界场景规则
- 修正测试数据的赋值错误
import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; public class TestStream { private List<Objs> getData() { List<Objs> objects = new ArrayList<>(); Objs objs1 = new Objs(); Objs objs2 = new Objs(); Objs objs3 = new Objs(); Objs objs4 = new Objs(); // 修正赋值顺序:每个对象设值完成后再加入列表 objs1.setObjId("1,2,3"); objects.add(objs1); objs2.setObjId("4,5,6"); objects.add(objs2); objs3.setObjId("7,84,3"); objects.add(objs3); objs4.setObjId(null); objects.add(objs4); return objects; } private List<Objs> test () { // 模拟sections入参,实际使用时替换为外部传入值即可 String sectionStr = "2,8"; // 预处理sections:空值/空串时转为空集合,符合场景4规则 Set<String> sectionSet; if (sectionStr == null || sectionStr.trim().isEmpty()) { sectionSet = new HashSet<>(); } else { sectionSet = Arrays.stream(sectionStr.split(",")) .map(String::trim) .collect(Collectors.toSet()); } List<Objs> objects = getData(); List<Objs> result = objects.stream() .filter(object -> { String objId = object.getObjId(); // 条件1:objId为null或空串,直接保留 if (objId == null || objId.trim().isEmpty()) { return true; } // sections为空集合时,非空objId直接不保留,符合场景4规则 if (sectionSet.isEmpty()) { return false; } // 条件2:拆分objId后和sections集合做精确匹配,有交集则保留 Set<String> objIdSet = Arrays.stream(objId.split(",")) .map(String::trim) .collect(Collectors.toSet()); return objIdSet.stream().anyMatch(sectionSet::contains); }) .skip(0) .limit(3) // 按需求设置每页3条 .collect(Collectors.toList()); return result; } public static void main(String[] args) { TestStream testStream= new TestStream(); List<Objs> result = testStream.test(); // 打印结果方便验证 result.forEach(obj -> System.out.println("命中对象objId:" + obj.getObjId())); } class Objs { private String objId; public void setObjId(String id) { objId = id;} public String getObjId() { return objId;} } }
逻辑验证说明
- 场景1:objId为
"1,2,3"、sections为"2,4"时,会匹配到共同元素"2",对象保留 - 场景2:objId为
"1,3"、sections为"2"时,无共同元素,对象过滤 - 场景3:objId为null/空串时,无论sections是什么值,对象直接保留
- 场景4:sections为null/空串时,只有objId为null/空串的对象会保留,其余全部过滤
- 不会出现子串误匹配:比如objId为
"7,84,3"、sections含"8"时,不会错误命中
内容的提问来源于stack exchange,提问作者pintekus
相关产品推荐
相关产品推荐

