使用Java流从员工列表中获取在特定加入日期之前和之后的员工


9

ListEmployees的不同加入日期。我想在使用流从List加入特定日期之前和之后获取员工。

我尝试下面的代码,

 List<Employee> employeeListAfter = employeeList.stream()
                .filter(e -> e.joiningDate.isAfter(specificDate))
                .collect(Collectors.toList());

List<Employee> employeeListBefore = employeeList.stream()
        .filter(e -> e.joiningDate.isBefore(specificDate))
        .collect(Collectors.toList());

class Employee{
    int id;
    String name;
    LocalDate joiningDate;
}

有没有办法在单个流中做到这一点?


1
您可以使用partitioningBy
Code_Mode

5
之前和之后-因此,您希望除该日期加入的员工以外的所有员工吗?
John3136

假设它是“至少成为一名雇员”,您将想要分成之前而不是之前,根本不关心。
JollyJoker

Answers:


16

您可以partitioningBy按以下方式使用,

Map<Boolean, List<Employee>> listMap = employeeList.stream()
        .collect(Collectors.partitioningBy(e -> e.joiningDate.isAfter(specificDate)));

List<Employee> employeeListAfter = listMap.get(true);
List<Employee> employeeListBefore = listMap.get(false);

partitioningBy返回一个收集器,该收集器根据谓词对输入元素进行分区,并将它们组织成一个Map<Boolean, List<T>>

请注意,这不会使用来处理员工specificDate


1
对代码的解释将很棒。
Vishwa Ratna

2
这并不能完全解决问题代码所要执行的工作-拥有员工的员工specificDate将进入false分区,而问题代码中的任何位置都不存在
Andronicus

添加如何specificDate.plusDays(1)解决该问题?specificDate仍然会存在false
Andronicus

然后它将在true分区中……
Andronicus

1
@Andronicus:只有OP知道此行为是错误还是功能。对我来说,不遗漏任何员工似乎更安全。
埃里克·杜米尼尔

9

如果您的列表中可以包含加入的specificDate条目,那么您可能会发现groupingBy有用的:

Map<Integer, List<Employee>> result = employeeList.stream()
    .map(emp -> new AbstractMap.SimpleEntry<>(specificDate.compareTo(emp.getJoiningDate()), emp))
    .collect(Collectors.groupingBy(entry -> entry.getKey() > 0 ? 1 : (entry.getKey() < 0 ? -1 : 0),
            Collectors.mapping(entry -> entry.getValue(), Collectors.toList())));

employeeListAfter = result.get(-1);
employeeListBefore = result.get(1);
employeeListOnSpecificDate = result.get(0);

result地图包含Employee按位置分组相对记载specificDate,所以你可以选择谁加入之前,之后或在指定日期。


这应该是公认的答案
Andronicus

2
-1。您所做的错误假设compareTo将仅返回-1、0或1。实际上LocalDate.compareTo可以返回任何int。
MikeFHay

1
@MikeFHay感谢您指出这一点。我进行了非常快速的测试,并得出了结论。更改了实现(突然看起来很复杂)。
ernest_k

2
@ernest_k:您可以使用原始文件compareTo并对其进行调用Integer.signum
埃里克·杜米尼尔

1
@JollyJoker以防万一,您可以链接到github中的特定行:like this。单击行号可以直接更改URL。如果您已经知道或不在乎,请随时忽略。;)
Eric Duminil

4

您需要使用该特定日期过滤掉员工。然后可以使用分区:

Map<Boolean, List<Employee>> partitioned = employeeList.stream()
    .filter(e -> !e.joiningDate.equals(specificDate))
    .collect(partitioningBy(e -> e.joiningDate.isAfter(specificDate)));

List<Employee> employeeListAfter = partitioned.get(true);
List<Employee> employeeListBefore = partitioned.get(false);

这将基于集合是否满足谓词来创建集合图。


partitioningBy 今天学到的。
Vishwa Ratna

不,您不能按日期进行过滤,因为它将仅过滤具有specificDate的员工
Code_Mode

@Code_Mode哦,是的,我错过了,谢谢!
Andronicus

2

您可以使用Collectors.groupingBy和使用compareTo方法根据以前,当前和将来的日期对员工列表进行分组

Map<Integer, List<Employee>> result = employeeList.stream()
            .collect(Collectors.groupingBy(e-> e.joiningDate.compareTo(specificDate)< 0 ? -1 : (e.joiningDate.compareTo(specificDate) == 0 ? 0 : 1)));

所以输出将是

key--> -1 ---> will have employees with previous date
key--> 0 ---> will have employees with current date
key--> 1 ---> will have employees with future date
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.