如何用Java Stream获取满足login=peter且status=SLEEP的JSON的itemid
问题:通过Java Stream筛选符合条件的itemid值
项目已引入Jackson库并定义了对应POJO类,现有如下JSON数组数据,需要通过Java Stream获取满足以下条件的itemid值:数据中存在login为peter的worker,且该worker包含status为SLEEP的状态。尝试了以下代码但未成功:
JSON数据
[ { "itemid": "bf47", "name": "test", "workers": [ { "user": { "id": "7074", "login": "john" }, "status": [ { "name": "WORK" } ] }, { "user": { "id": "1237", "login": "peter" }, "status": [ { "name": "WORK" }, { "name": "SLEEP" } ] } ] }, { "itemid": "ea277", "name": "test", "workers": [ { "user": { "id": "2ce0", "login": "robert" }, "status": [ { "name": "WORK" } ] } ] } ]
尝试的Java代码
String id = Arrays.stream(allItemId).flatMap(x->x.getworkers().stream()) .filter(x->x.getUser().getLogin().equals(peter)) .flatMap(x->x.getStatus().stream()) .filter(x->x.getName().equals("SLEEP")).map(x->x.getItemId).findFirst().get();
问题分析与解决方法
原代码问题
- 丢失原Item引用:使用
flatMap展开workers后,后续操作对象变为Worker;再展开status后对象变为Status,此时x.getItemId完全无效——Status类不存在该方法。 - 筛选逻辑顺序错误:应该先对每个Item判断是否存在符合条件的Worker,而非直接展开所有Worker和Status,导致无法关联回原Item的itemid。
正确实现代码
假设POJO类分别为Item、Worker、User、Status,且所有字段的getter方法定义正确:
// 用Optional安全处理无匹配结果的情况 Optional<String> targetItemId = Arrays.stream(allItemId) .filter(item -> // 检查当前Item的workers中是否存在符合条件的worker item.getWorkers().stream().anyMatch(worker -> // worker的login是peter "peter".equals(worker.getUser().getLogin()) // 且该worker包含status为SLEEP的状态 && worker.getStatus().stream().anyMatch(status -> "SLEEP".equals(status.getName())) ) ) // 提取符合条件的Item的itemid .map(Item::getItemid) // 获取第一个匹配结果(若存在) .findFirst(); // 安全获取结果,避免无匹配时抛出NoSuchElementException String id = targetItemId.orElse(null); // 也可根据业务需求处理空值,比如抛出自定义异常: // String id = targetItemId.orElseThrow(() -> new IllegalArgumentException("未找到符合条件的itemid"));
代码逻辑说明
- 遍历所有Item对象,先对每个Item做筛选:
- 检查该Item的workers列表中,是否存在login为
peter的Worker - 同时该Worker的status列表中,是否包含name为
SLEEP的状态
- 检查该Item的workers列表中,是否存在login为
- 找到第一个符合条件的Item后,提取它的
itemid - 使用
Optional包装结果,避免直接调用get()在无匹配时抛出异常,保证代码健壮性
内容的提问来源于stack exchange,提问作者Joel Andersson
相关产品推荐
相关产品推荐

