Obtenga empleados antes y después de una fecha específica de afiliación de la Lista de empleados con flujo Java

9

Tengo Listde Employees con diferentes fechas de ingreso. Quiero obtener empleados antes y después de una fecha específica de unirse a la lista mediante transmisiones.

Intenté seguir el 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;
}

¿Hay alguna manera de hacer esto en una sola secuencia?

Rajiv
fuente
1
Puede usarpartitioningBy
Code_Mode
55
Antes y después, ¿entonces quiere todos los empleados excepto aquellos que se unieron en la fecha?
John3136
Suponiendo que "ha sido un empleado al menos desde entonces", querrá dividirse en antes y no antes, sin preocuparse por nada en absoluto.
JollyJoker

Respuestas:

16

Puedes usar partitioningBylo siguiente,

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

PartitionBy Devuelve un recopilador que divide los elementos de entrada de acuerdo con un predicado y los organiza en unMap<Boolean, List<T>>

Tenga en cuenta que esto no manejará a los empleados con specificDate.

Code_Mode
fuente
1
Una explicación del código será genial.
Vishwa Ratna
2
Esto no hace exactamente lo que hace el código en cuestión: los empleados con specificDateaterrizarán en la falsepartición, donde está el código en cuestión en ninguno
Andronicus
¿Cómo la specificDate.plusDays(1)resolución resuelve el problema? specificDateaún estará en la falseparte.
Andronicus
Entonces estará en la truepartición ...
Andronicus
1
@Andronicus: Solo OP sabe si este comportamiento es un error o una característica. Para mí, parece más seguro no dejar afuera a ningún empleado.
Eric Duminil
9

Si su lista puede tener entradas que se unieron en elspecificDate , entonces puede resultarle 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);

El resultmapa contiene Employeeregistros agrupados por posición relativa a specificDate, por lo que puede elegir quién se unió antes, después o en la fecha especificada.

ernest_k
fuente
Esta debería ser la respuesta aceptada
Andronicus
2
-1. Está haciendo la suposición falsa que compareTosolo devolverá -1, 0 o 1. De hecho, LocalDate.compareTo puede devolver cualquier int.
MikeFHay
1
@ MikeFHay Gracias por señalar eso. Hice una prueba muy rápida y saqué conclusiones. Se modificó la implementación (y de repente parece complejo).
ernest_k
2
@ernest_k: Puedes usar el original compareToy llamarlo Integer.signum.
Eric Duminil
1
@JollyJoker Sólo en caso de que no lo sabía, se puede vincular a una línea específica en github: como este . Al hacer clic en el número de línea, la URL cambia directamente. Siéntase libre de ignorar si ya lo sabía o no le importa. ;)
Eric Duminil
4

Debe filtrar a los empleados con esta fecha en particular. Entonces puedes usar la partición:

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

Esto creará un mapa de colecciones en función de si cumplen el predicado.

Andronicus
fuente
Aprendí partitioningBy hoy.
Vishwa Ratna
No, no puede filtrar con fecha, ya que filtraría a los empleados con solo
Fecha
@Code_Mode oh, sí, me perdí eso, ¡gracias!
Andronicus
2

Puede usar Collectors.groupingByy usar el compareTométodo para agrupar la lista de empleados en función de la fecha anterior, actual y 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)));

Entonces la salida 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
Consorcio inactivo
fuente