Obter funcionários antes e depois da data específica de ingresso na lista de funcionários com o fluxo Java

9

Tenho Listde Employees com diferentes datas de união. Desejo obter funcionários antes e depois da data específica de ingresso na lista usando fluxos.

eu tentei seguir o código,

 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;
}

Existe alguma maneira de fazer isso no fluxo único?

Rajiv
fonte
11
Você pode usarpartitioningBy
Code_Mode
5
Antes e depois - então você quer todos os funcionários, exceto os que se juntaram à data?
John3136 3/01
Supondo que "tenha sido um funcionário pelo menos desde", você desejará se dividir antes e não antes, sem se preocupar com nada.
JollyJoker

Respostas:

16

Você pode usar partitioningBycomo abaixo,

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 Retorna um coletor que particiona os elementos de entrada de acordo com um predicado e os organiza em umMap<Boolean, List<T>>

Observe que isso não vai lidar com funcionários specificDate.

Code_Mode
fonte
11
Uma explicação do código será ótima.
Vishwa Ratna
2
Isso não faz exatamente o que o código em questão faz - os funcionários com specificDateaterrissarão na falsepartição, o que ocorre no código em questão
Andronicus
Como a adição specificDate.plusDays(1)resolve o problema? specificDateainda estará na falseparte.
Andronicus
Então ele estará na truepartição ...
Andronicus
11
@ Andronicus: Somente o OP sabe se esse comportamento é um bug ou um recurso. Para mim, parece mais seguro não deixar nenhum funcionário de fora.
Eric Duminil
9

Se sua lista puder ter entradas que se juntaram aospecificDate , você poderá achar groupingByútil:

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);

O resultmapa contém Employeeregistros agrupados por posição relativamente a specificDate, para que você possa escolher quem ingressou antes, depois ou na data especificada.

ernest_k
fonte
Esta deve ser a resposta aceita
Andronicus
2
-1. Você está assumindo que falso compareToretornará apenas -1, 0 ou 1. De fato, LocalDate.compareTo pode retornar qualquer int.
MikeFHay
11
@ MikeFHay Obrigado por apontar isso. Fiz um teste muito rápido e tirei conclusões precipitadas. Implementação alterada (e de repente parece complexa).
ernest_k 3/01
2
@ernest_k: Você pode usar o original compareToe acessá Integer.signum-lo.
Eric Duminil 03/01
11
@JollyJoker Apenas no caso de você não sabia, você pode conectar-se a uma linha específica no github: como este . Clicar no número da linha altera o URL diretamente. Sinta-se livre para ignorar se você já sabia ou não se importa. ;)
Eric Duminil 03/01
4

Você precisa filtrar os funcionários com essa data específica. Então você pode usar o particionamento:

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);

Isso criará um mapa de coleções com base em se elas cumprem o predicado.

Andronicus
fonte
Aprendi partitioningBy hoje.
Vishwa Ratna
Não, você não pode filtrar com data, pois
filtraria
@ Code_Mode oh, sim, eu perdi isso, obrigado!
Andronicus
2

Você pode usar Collectors.groupingBye usar o compareTométodo para agrupar a lista de funcionários com base nas datas anterior, atual e futura

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

Então a saída será

key--> -1 ---> will have employees with previous date
key--> 0 ---> will have employees with current date
key--> 1 ---> will have employees with future date
Piscina morta
fonte