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?


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.


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.


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.


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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.