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

Java11如何按自定义条件过滤复杂对象列表,实现按字段规则去重

Java 自定义规则分组去重实现方案

你原有思路方向正确,问题出在Comparator的实现不符合JDK规范:Comparator的compare(o1, o2)方法要求返回int值,正数代表o1排序优先级高于o2,负数代表o1排序优先级低于o2,0代表二者优先级相等,你之前直接返回对象属于语法错误,且优先级判断逻辑不完整。

方案1(易扩展写法,推荐)

通过优先级映射表定义device的优先级,后续新增设备类型时只需修改映射表即可:

// 定义设备优先级,数值越大优先级越高
Map<String, Integer> devicePriority = Map.of(
    "Phone", 2,
    "Laptop", 1
);

List<Employee> reducedEmpList = empList.stream()
    .collect(Collectors.groupingBy(
        Employee::getEmployeeId,
        // 每组取优先级最高的记录
        Collectors.maxBy(Comparator.comparingInt(emp -> 
            devicePriority.getOrDefault(emp.getDevice().trim().toUpperCase(), 0)
        ))
    ))
    .values()
    .stream()
    // 业务场景下按employeeId分组至少存在一条记录,直接拆解Optional即可
    .map(Optional::get)
    .collect(Collectors.toList());

方案2(无额外依赖写法)

无需单独定义优先级映射表,直接在Comparator中实现优先级判断:

List<Employee> reducedEmpList = empList.stream()
    .collect(Collectors.groupingBy(
        Employee::getEmployeeId,
        Collectors.maxBy((e1, e2) -> {
            int p1 = "Phone".equalsIgnoreCase(e1.getDevice()) ? 2 : "Laptop".equalsIgnoreCase(e1.getDevice()) ? 1 : 0;
            int p2 = "Phone".equalsIgnoreCase(e2.getDevice()) ? 2 : "Laptop".equalsIgnoreCase(e2.getDevice()) ? 1 : 0;
            return Integer.compare(p1, p2);
        })
    ))
    .values()
    .stream()
    .map(Optional::get)
    .collect(Collectors.toList());

逻辑说明

  • 首先通过Collectors.groupingBy按employeeId将同一员工的所有记录聚合到同一组
  • 对每组内的记录,根据device计算优先级,Phone优先级高于Laptop,用Collectors.maxBy筛选出每组优先级最高的记录
  • 最后提取分组结果的value,拆解Optional包装后收集为最终的去重列表

扩展提示

如果同一员工存在多条同优先级的记录(例如两条Phone记录),可在Comparator中追加额外的比较规则(比如按记录更新时间倒序),即可实现更复杂的筛选逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 04:06:03