java - Recuperando la lista de empleados con el salario más bajo usando stream
lambda java-8 (5)
Esta pregunta ya tiene una respuesta aquí:
Estoy tratando de recuperar una lista de aquellos con el salario más bajo de una lista de empleados. Hasta ahora he logrado encontrar al empleado con el salario más bajo, pero quiero recuperar varios si varios empleados tienen el mismo salario.
Creo que se supone que la solución está en una línea. Por lo tanto, no puedo crear una variable con el salario más bajo y solo verifico en cada una de ellas ''Salario menor o igual a Low_Salary''. Intenté esto, y funcionó.
Así que creo que mi problema es que ".min (comparador)" recupera solo uno de los más bajos.
Comparator<Employee> comparator = Comparator.comparing( Employee :: getSalary);
List<Employee> lowSalary = employees.stream()
.min(comparator)
.stream()
.collect(Collectors.toList());
lowSalary.forEach(System.out::println);
Primero cree un
TreeMap
, cuya clave es el salario.
TreeMap
ordena sus entradas por su clave.
Luego tome la primera entrada, que es la entrada con el salario más bajo y obtenga los valores asociados con eso.
Esta solución itera sobre la lista solo una vez.
Así es como se ve.
List<Employee> empsWithLowestSalary = employees.stream()
.collect(Collectors.groupingBy(Employee::getSalary, TreeMap::new, Collectors.toList()))
.firstEntry()
.getValue();
TreeMap
almacena elementos del mapa en un árbol Rojo-Negro.
El costo de inserción para un elemento en el árbol Rojo-Negro es
O(Log (n))
.
Como estamos insertando
n
elementos, la complejidad total del tiempo de esta solución es
O(n Log (n))
.
Para
firstEntry()
, lleva tiempo constante
O(1)
, ya que mantiene un puntero a los nodos de hoja más a la izquierda y a la derecha en el árbol, respectivamente.
El nodo de la izquierda representa el valor más pequeño en el árbol, mientras que el nodo de la hoja de la derecha representa el valor más alto.
Simplemente siguiendo esta gran respuesta , pensé en escribir un recopilador personalizado que sirva a nuestro propósito. Este recopilador itera sobre la Lista solo una vez y su complejidad de tiempo de ejecución se encuentra en O (n), que supera significativamente el enfoque anterior. Además, le permite escribir su código de cliente en una sola declaración. Así es como se ve.
static <T> Collector<T, ?, List<T>> minList(Comparator<? super T> comp) {
return Collector.of(ArrayList::new, (list, t) -> {
int c;
if (list.isEmpty() || (c = comp.compare(t, list.get(0))) == 0)
list.add(t);
else if (c < 0) {
/*
* We have found a smaller element than what we already have. Clear the list and
* add this smallest element to it.
*/
list.clear();
list.add(t);
}
}, (list1, list2) -> {
if (comp.compare(list1.get(0), list2.get(0)) < 0)
return list1;
else if (comp.compare(list1.get(0), list2.get(0)) > 0)
return list2;
else {
list1.addAll(list2);
return list1;
}
});
}
Y aquí está tu código de cliente.
Collection<Employee> empsWithLowestSalary = employees.stream()
.collect(minList(Comparator.comparing(Employee::getSalary)));
Puede agrupar por salario y luego recuperar la lista de empleados con salario mínimo:
List<Employee> employees = new ArrayList<Employee>(){{
add(new Employee("bilbo baggins", 10));
add(new Employee("frodo baggins", 10));
add(new Employee("gandalf grey", 100));
}};
Map<Integer, List<Employee>> result = employees.stream().collect(groupingBy(Employee::getSalary));
List<Employee> allMin = result.entrySet().stream()
.min(Comparator.comparing(Map.Entry::getKey))
.map(Map.Entry::getValue)
.orElse(Collections.emptyList());
allMin.forEach(System.out::println);
Salida
Employee{name=''bilbo baggins'', salary=10}
Employee{name=''frodo baggins'', salary=10}
Puede calcular el salario mínimo primero y luego usarlo en su condición de
Stream#filter
:
int salary =
employees.stream()
.min(Comparator.comparing(Employee::getSalary))
.map(e -> e.getSalary())
.orElse(-1);
List<Employee> emps =
employees.stream()
.filter(emp -> emp.getSalary() == salary)
.collect(Collectors.toList());
Puede obtener primero el empleado de salario mínimo y luego filtrar por él,
Comparator<Employee> comparator = Comparator.comparing( Employee :: getSalary);
Optional<Employee> min = employees.stream()
.min(comparator);
List<Employee> lowSalary = employees.stream()
.filter(ele->ele.salary==min.get().salary)
.collect(Collectors.toList());
Integer lowestSalary = employees.stream()
.min(Comparator.comparing(Employee::getSalary))
.map(Employee::getSalary).get();
List<Employee> employeesWithLowestSalary = employees.stream()
.filter(e -> e.getSalary() == lowestSalary)
.collect(Collectors.toList());
Comience por encontrar cuál es el salario más bajo y luego filtre la lista de empleados para que solo tenga empleados cuyo salario coincida.