You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于条件过滤列表,用Stream保留相同日期下value最大的对象?

实现方案

完全可以通过Java Streams实现该需求,更推荐使用Collectors.groupingBy分组收集的方式实现,逻辑清晰且线程安全,不需要额外自定义Predicate也可完成,具体实现如下:

前置假设

你的MyObject类已实现对应字段的getter方法:

class MyObject {
    private Date date;
    private int value;

    public Date getDate() { return date; }
    public int getValue() { return value; }
}

方案1:分组收集法(推荐)

核心逻辑是先按日期对元素分组,每组只保留value最大的元素,最后提取分组结果转为列表:

import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

// 你的原始列表
List<MyObject> originalList = ...;

List<MyObject> filteredList = originalList.stream()
        .collect(Collectors.groupingBy(
                // 按日期分组
                MyObject::getDate,
                // 每组取value最大的元素,解包Optional
                Collectors.collectingAndThen(
                        Collectors.maxBy(Comparator.comparingInt(MyObject::getValue)),
                        optional -> optional.orElseThrow(() -> new IllegalArgumentException("空分组异常"))
                )
        ))
        // 提取所有分组的结果转成列表
        .values()
        .stream()
        // JDK16以下版本替换为.collect(Collectors.toList())
        .toList();

方案2:结合状态Predicate实现

如果需要和Predicate配合使用,可以自定义带状态的Predicate记录已经出现过的日期对应的最大value,但是注意该方式不支持并行流,存在线程安全风险:

import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;

Predicate<MyObject> maxValueFilter = new Predicate<>() {
    // 存储日期对应的已记录最大value
    private final Map<Date, Integer> dateMaxMap = new HashMap<>();

    @Override
    public boolean test(MyObject obj) {
        // 当前日期未记录,或当前对象value大于已记录最大值时更新缓存并返回true
        if (!dateMaxMap.containsKey(obj.getDate()) || obj.getValue() > dateMaxMap.get(obj.getDate())) {
            dateMaxMap.put(obj.getDate(), obj.getValue());
            return true;
        }
        return false;
    }
};

List<MyObject> filteredList = originalList.stream()
        .filter(maxValueFilter)
        // 二次去重,移除同一个日期下先出现的小value元素
        .collect(Collectors.groupingBy(
                MyObject::getDate,
                Collectors.collectingAndThen(
                        Collectors.maxBy(Comparator.comparingInt(MyObject::getValue)),
                        optional -> optional.orElseThrow()
                )
        ))
        .values()
        .stream()
        .toList();

注意事项

  • 作为分组key的Date类需要正确重写equals()和hashCode()方法,JDK自带的java.util.Date已经满足要求,若为自定义日期类需额外实现。
  • 涉及多线程并行流场景时,仅推荐使用方案1,状态Predicate在并行场景下会出现数据错乱。

内容的提问来源于stack exchange,提问作者qwertyqwerty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 04:09:01