MST

星途 面试题库

面试题:Java Stream多方法组合下的性能优化与顺序调整

给定一个包含大量员工对象的List<Employee>,Employee类有属性name(字符串)、age(整数)、salary(双精度浮点数)。需求是先过滤出年龄大于30岁的员工,然后对这些员工按照工资从高到低排序,最后取出工资最高的前3名员工的名字。请使用Java Stream实现该功能,并分析在多方法组合过程中,如何调整方法顺序以优化性能,例如是否可以提前截断流操作?
48.8万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试
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);
    }
}

性能优化分析

  1. 提前截断流操作:在这个场景中,limit(3)操作就是提前截断流的操作。因为我们只需要工资最高的前3名员工,所以在排序后尽早使用limit(3)可以避免对剩余元素进行不必要的处理。如果先进行map操作,将员工对象转换为名字字符串后再进行limit,那么就无法利用提前截断流的优化,因为map操作会对整个流进行遍历。所以应该先进行过滤、排序,然后尽早使用limit,最后再进行map操作。这样在limit截断流后,map操作只需要处理前3个元素,而不是处理所有年龄大于30岁的员工。

  2. 减少中间操作:尽量减少中间操作的数量,虽然这里的操作已经比较精简,但如果在复杂场景中有一些不必要的中间操作,应考虑去除。例如,如果在过滤和排序之间有一些不必要的映射操作,可以考虑将其合并或去除,以减少流遍历的次数。

  3. 并行流的使用:如果员工数量非常大,可以考虑使用并行流employees.parallelStream()来利用多核CPU的优势提高处理速度。但要注意,并行流可能会带来线程安全和资源竞争等问题,并且在数据量较小的情况下,并行流的开销可能会大于其带来的性能提升。