4 回答
TA贡献1799条经验 获得超8个赞
首先创建一个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)
,因为它分别维护一个指向树中最左边和最右边叶节点的指针。最左边的节点代表树中的最小值,而最右边的叶节点代表树中的最高值。
我想到编写一个服务于我们目的的自定义收集器。该收集器仅对 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)));
TA贡献1796条经验 获得超7个赞
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());
首先查找最低工资是多少,然后过滤员工列表,以便只包含工资匹配的员工。
TA贡献1777条经验 获得超10个赞
您可以按工资分组,然后检索最低工资的员工列表:
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}
TA贡献1884条经验 获得超4个赞
您可以先计算最低工资,然后根据您的情况使用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());
添加回答
举报