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

如何用Java Stream实现按人员每日去重过滤嵌套TimeOffSlot列表?

问题分析

你的代码存在两个核心问题:

  1. 语法错误:第二个filter方法的参数逻辑错误,slot.getPersonTimeOffList.stream().filter(distinctByKey(...))返回的是Stream对象,无法直接作为Predicate(需要返回boolean)传入外层filter,会直接编译失败。
  2. 逻辑偏差:需求是为每个人员保留当天的第一个/最早的TimeOffSlot,但原代码试图过滤Slot内部的人员列表,完全没触碰到“按人员去重并保留对应Slot”的核心逻辑。
解决方案

核心思路是:先拆分Slot与人员的关联关系,按人员分组后保留每个人员的首个Slot,最后去重重复的Slot(因为一个Slot可能对应多个人员)。

完整实现代码

// 第一步:过滤出当天的所有TimeOffSlot
Collection<TimeOffSlot> todaySlots = timeOffSlots.stream()
        .filter(slot -> slot.getSlotDate().equals(LocalDate.now()))
        .collect(Collectors.toList());

// 第二步:按人员ID分组,为每个人员保留当天最早的TimeOffSlot
Map<Long, TimeOffSlot> personToFirstSlot = todaySlots.stream()
        // 把每个Slot拆成【人员ID - Slot】的映射条目(一个Slot对应多个人则拆多条)
        .flatMap(slot -> slot.getPersonTimeOffList().stream()
                .map(personSlot -> new AbstractMap.SimpleEntry<>(personSlot.getPerson().getPersonId(), slot)))
        // 按人员ID分组,遇到同一人员的多个Slot时,保留时间更早的那个
        .collect(Collectors.toMap(
                Map.Entry::getKey,
                Map.Entry::getValue,
                (existingSlot, newSlot) -> existingSlot.getSlotTime().isBefore(newSlot.getSlotTime()) ? existingSlot : newSlot
        ));

// 第三步:提取最终Slot列表,用LinkedHashSet去重(避免一个Slot被多个人员关联而重复出现)
Collection<TimeOffSlot> filteredSlots = new ArrayList<>(new LinkedHashSet<>(personToFirstSlot.values()));

关键逻辑说明

  • 拆分关联:用flatMap把每个TimeOffSlot拆成多个「人员ID-Slot」对,解决一个Slot对应多个人的情况。
  • 分组去重:Collectors.toMap的第三个参数是合并规则,这里选择保留时间更早的Slot;如果只想保留列表中第一个出现的Slot,把合并规则改成(existing, newSlot) -> existing即可。
  • 去重Slot:用LinkedHashSet保证Slot的唯一性和顺序,避免同一个Slot因关联多个人员而重复出现在结果里。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 18:55:33