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