使用流检索薪水最低的员工列表

时间:2019-09-13 12:30:55

标签: java lambda java-8 java-stream

我正在尝试从员工列表中检索薪水最低的列表。到目前为止,我设法找到了薪水最低的 the 员工,但是如果几个员工的薪水相同,我想检索多个员工。

我认为解决方案应该在同一行。因此,我无法创建一个薪水最低的变量,而只能检查每个薪水是否小于或等于Low_Salary。我尝试了一下,它奏效了。

所以我相信我的问题是“ .min(comparator)”仅检索最低的一个。

Comparator<Employee> comparator = Comparator.comparing( Employee :: getSalary);
List<Employee> lowSalary = employees.stream()
               .min(comparator)
               .stream()
               .collect(Collectors.toList());
lowSalary.forEach(System.out::println);

5 个答案:

答案 0 :(得分:13)

首先创建一个TreeMap,其关键是薪水。 TreeMap按其键对条目进行排序。然后获取第一个条目,即薪水最低的条目,并掌握与此相关的值。此解决方案仅对列表进行一次迭代。看起来就是这样。

List<Employee> empsWithLowestSalary = employees.stream()
    .collect(Collectors.groupingBy(Employee::getSalary, TreeMap::new, Collectors.toList()))
    .firstEntry()
    .getValue();

TreeMap将地图元素存储在红黑树中。红黑树中一个元素的插入成本为O(Log (n))。由于我们要插入n个元素,因此此解决方案的总时间复杂度为O(n Log (n))。对于firstEntry(),它花费恒定的时间O(1),因为它维护着分别指向树中最左边和最右边叶子节点的指针。最左边的节点代表树中的最小值,而最右边的叶子节点代表树中的最大值。

仅遵循此great answer,我就想编写一个满足我们目的的自定义收集器。该收集器仅对List进行一次迭代,其运行时复杂度为O(n),明显优于上述方法。此外,它允许您在一个语句中编写客户代码。看起来就是这样。

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

这是您的客户代码。

Collection<Employee> empsWithLowestSalary = employees.stream()
                .collect(minList(Comparator.comparing(Employee::getSalary)));

答案 1 :(得分:2)

您可以按薪水分组,然后检索最低薪水的雇员列表:

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

输出

Employee{name='bilbo baggins', salary=10}
Employee{name='frodo baggins', salary=10}

答案 2 :(得分:2)

您可以先获取最低薪水雇员,然后再按其筛选,

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

答案 3 :(得分:1)

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

首先找到最低工资是多少,然后过滤员工列表,以便只有薪水匹配的员工。

答案 4 :(得分:1)

您可以先计算最低工资,然后在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());