1. 概述

在本篇文章中,我们将学习如何使用 **Java 8 Streams**,根据一个列表中的值来筛选另一个列表中的对象。

这种场景在实际开发中很常见,比如我们要从员工列表中找出属于“销售部”的员工,而部门信息却在另一个列表中。这就需要我们通过 Stream API 实现跨列表的匹配与过滤。

2. 实体类准备

我们先定义两个实体类:Employee(员工) 和 Department(部门):

class Employee {
    Integer employeeId;
    String employeeName;

    // getters and setters
}

class Department {
    Integer employeeId;
    String department;

    // getters and setters
}

⚠️ 注意:这两个类通过 employeeId 字段关联。

3. 根据另一个列表筛选包含特定值的对象

我们的目标是:从 Employee 列表中筛选出那些:

  • 所属部门为 “sales”
  • 并且其 employeeId 存在于 Department 列表中

✅ 简单粗暴的实现方式就是嵌套 Stream 并使用 anyMatch() 方法:

@Test
public void givenDepartmentList_thenEmployeeListIsFilteredCorrectly() {
    Integer expectedId = 1002;

    populate(emplList, deptList);

    List<Employee> filteredList = emplList.stream()
      .filter(empl -> deptList.stream()
        .anyMatch(dept -> 
          dept.getDepartment().equals("sales") && 
          empl.getEmployeeId().equals(dept.getEmployeeId())))
        .collect(Collectors.toList());

    assertEquals(1, filteredList.size());
    assertEquals(expectedId, filteredList.get(0)
      .getEmployeeId());
}

📌 这里我们做了两层 Stream 过滤:

  • 外层遍历员工列表
  • 内层检查该员工是否在部门列表中存在匹配项,并满足部门为 “sales”

最终将符合条件的员工收集到 filteredList 中。

4. 根据另一个列表筛选排除特定值的对象

接下来换个方向:我们要从 Department 列表中筛选出那些:

  • employeeId 不在某个员工 ID 列表中
  • 比如排除所有“销售部”的员工

✅ 实现方式更直接,只需要对 employeeIdList 使用 contains() 取反即可:

@Test
public void givenEmployeeListToExclude_thenDepartmentListIsFilteredCorrectly() {
    String expectedDepartment = "sales";

    List<Integer> employeeIdList = Arrays.asList(1001, 1002, 1004, 1005);

    populate(employeeList, departmentList);
  
    List<Department> filteredList = departmentList.stream()
      .filter(dept -> !employeeIdList.contains(dept.getEmployeeId()))
      .collect(Collectors.toList());

    assertNotEquals(expectedDepartment, department.getDepartment());
}

📌 这里我们:

  • 构造了一个要排除的员工 ID 列表
  • 使用 !contains() 排除这些 ID 对应的部门
  • 最终得到的是不包含这些员工的部门列表

5. 总结

在这篇文章中,我们掌握了以下关键点:

  • ✅ 如何通过 Collection#stream() 将一个列表的数据流式处理到另一个列表中
  • ✅ 如何使用 anyMatch() 组合多个过滤条件
  • ✅ 如何实现“包含”和“排除”两种筛选策略

如果你在做数据匹配或列表过滤时遇到类似需求,这些技巧都能派上用场。

📄 完整源码可以在 GitHub 上找到:core-java-collections-list-2


原始标题:Java Streams: Find Items From One List Based on Values From Another List | Baeldung