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

问题描述:

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

I'm trying to retrieve a list of those with lowest salary from a list of employees. So far I've managed to find the employee with lowest salary, but I want to retrieve multiple if several employees have the same salary.

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

I think the solution is supposed to be in one line. So I can't create a variable with the lowest salary and just check each one for 'Salary less than or equal to Low_Salary'. I tried this, and it worked.

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

So I believe my problem is that ".min(comparator)" retrieves only one of the lowest.

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

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

First create a TreeMap, whose key is the salary. TreeMap sorts it's entries by it's key. Then grab the first entry, which is the entry with the lowest salary and get hold of the values associated with that. This solution iterates over the list only once. Here's how it looks.

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),因为它维护着分别指向树中最左边和最右边叶子节点的指针.最左边的节点代表树中的最小值,而最右边的叶子节点代表树中的最大值.

TreeMap stores map elements in a Red-Black tree. The insertion cost for one element in Red-Black tree is O(Log (n)). Since we are inserting n elements, the total Time complexity of this solution is O(n Log (n)). For the firstEntry(), it takes constant time O(1), since it maintains a pointer to the leftmost and rightmost leaf nodes in the tree respectively. The leftmost node represent the smallest value in the tree whereas the rightmost leaf node represents the highest value.

只需遵循以下很好的答案,我想到编写一个符合我们目的的自定义收集器.该收集器仅对List进行一次迭代,其运行时复杂度为O(n),明显优于上述方法.此外,它允许您在一个语句中编写客户代码.这是它的外观.

Just by following this great answer, I thought of writing a custom collector that serves our purpose. This collector iterates over the List only once and it's runtime complexity lies at O(n), which significantly outperforms the above approach. Furthermore it allows you to write your client code in one single statement. Here's how it looks.

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