Java Stream如何对除最大值外的符合条件元素执行赋值操作
Java Stream按属性最大值区分批量设置对象属性方案
问题背景
当前已实现的逻辑可以从对象列表中筛选出满足以下两个条件的对象,将其中stageNo最大的对象的flag属性设为1:
- 对象的
stageNoCalculate值等于当前对象的stageNo - 对象的
executionDate非空
现有代码如下:
Object currentObject = new Object(); List<Object> objects = new ArrayList<>(); objects .stream() .filter(object -> object.stageNoCalculate == currentObject.getStageNo) .filter(object -> object.executionDate != null) .max(Comparator.comparing(Object::getStageNo) .map(object -> { object.setFlag(1); return object; }).get();
需要补充实现逻辑:对所有满足相同过滤条件、但stageNo不是最大值的剩余对象,统一设置flag=0。
推荐实现
优先选择逻辑清晰、易维护的写法,性能损耗在绝大多数业务场景下可以忽略,代码如下:
// 注意:请将MyStageObj替换为你实际的业务实体类,不要直接用顶层Object类 MyStageObj currentObject = new MyStageObj(); List<MyStageObj> objects = new ArrayList<>(); // 统一抽离过滤规则,避免两处判断逻辑不一致 Predicate<MyStageObj> filterRule = item -> item.stageNoCalculate == currentObject.getStageNo() && item.executionDate != null; // 先计算符合过滤规则的对象中最大的stageNo值 int maxStageVal = objects.stream() .filter(filterRule) .mapToInt(MyStageObj::getStageNo) .max() // 无符合条件数据时给默认值,避免直接调用get()抛出NoSuchElementException .orElse(Integer.MIN_VALUE); // 统一遍历所有符合规则的对象,按stageNo是否为最大值分别赋值 objects.stream() .filter(filterRule) .forEach(item -> item.setFlag(item.getStageNo() == maxStageVal ? 1 : 0));
注意事项
- 原代码存在语法问题:
currentObject.getStageNo是方法调用,需要加括号写成currentObject.getStageNo();max()方法的括号未闭合,会直接编译报错。 - 原代码直接调用Optional的
get()方法存在风险:当列表中没有符合过滤条件的对象时,会直接抛出NoSuchElementException,生产环境建议用orElse、ifPresent等安全方法处理空值场景。 - 如果数据量级特别大(十万级以上)需要优化为单次遍历,可以自定义Collector在遍历过程中同时记录最大stageNo、对应对象、其余符合条件的对象列表,遍历结束后统一赋值,但这种写法可读性较差,非性能瓶颈场景不推荐使用。
内容的提问来源于stack exchange,提问作者Daniel R
相关产品推荐
相关产品推荐

