面试题答案
一键面试import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
class Employee {
private String name;
private int age;
private double salary;
public Employee(String name, int age, double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public double getSalary() {
return salary;
}
}
public class Main {
public static void main(String[] args) {
List<Employee> employees = new ArrayList<>();
// 假设这里添加了大量员工对象
employees.add(new Employee("Alice", 35, 5000.0));
employees.add(new Employee("Bob", 28, 4500.0));
employees.add(new Employee("Charlie", 32, 5500.0));
employees.add(new Employee("David", 38, 6000.0));
employees.add(new Employee("Eve", 31, 5200.0));
List<String> top3Names = employees.stream()
.filter(employee -> employee.getAge() > 30)
.sorted(Comparator.comparingDouble(Employee::getSalary).reversed())
.limit(3)
.map(Employee::getName)
.collect(Collectors.toList());
System.out.println(top3Names);
}
}
性能优化分析
-
提前截断流操作:在这个场景中,
limit(3)
操作就是提前截断流的操作。因为我们只需要工资最高的前3名员工,所以在排序后尽早使用limit(3)
可以避免对剩余元素进行不必要的处理。如果先进行map
操作,将员工对象转换为名字字符串后再进行limit
,那么就无法利用提前截断流的优化,因为map
操作会对整个流进行遍历。所以应该先进行过滤、排序,然后尽早使用limit
,最后再进行map
操作。这样在limit
截断流后,map
操作只需要处理前3个元素,而不是处理所有年龄大于30岁的员工。 -
减少中间操作:尽量减少中间操作的数量,虽然这里的操作已经比较精简,但如果在复杂场景中有一些不必要的中间操作,应考虑去除。例如,如果在过滤和排序之间有一些不必要的映射操作,可以考虑将其合并或去除,以减少流遍历的次数。
-
并行流的使用:如果员工数量非常大,可以考虑使用并行流
employees.parallelStream()
来利用多核CPU的优势提高处理速度。但要注意,并行流可能会带来线程安全和资源竞争等问题,并且在数据量较小的情况下,并行流的开销可能会大于其带来的性能提升。