MST

星途 面试题库

面试题:Java中Java Stream与传统foreach在复杂业务下代码简洁性的高级难度题

假设你有一个包含多个员工对象的列表,员工对象包含姓名、年龄、工资等属性。需要实现一个功能,筛选出年龄大于30岁且工资大于10000的员工,然后按照工资从高到低排序,最后获取这些员工的姓名并拼接成一个字符串。分别用Java Stream和传统foreach实现该功能,并详细分析Stream在处理这种复杂业务逻辑时,代码简洁性体现在哪些方面,与传统foreach相比,代码结构和可读性有何差异。
41.7万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

Java Stream实现

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 EmployeeFiltering {
    public static void main(String[] args) {
        List<Employee> employees = new ArrayList<>();
        employees.add(new Employee("Alice", 35, 12000));
        employees.add(new Employee("Bob", 28, 9000));
        employees.add(new Employee("Charlie", 32, 15000));
        employees.add(new Employee("David", 25, 8000));
        employees.add(new Employee("Eve", 38, 13000));

        String result = employees.stream()
               .filter(employee -> employee.getAge() > 30 && employee.getSalary() > 10000)
               .sorted(Comparator.comparingDouble(Employee::getSalary).reversed())
               .map(Employee::getName)
               .collect(Collectors.joining());

        System.out.println(result);
    }
}

传统foreach实现

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

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 EmployeeFiltering {
    public static void main(String[] args) {
        List<Employee> employees = new ArrayList<>();
        employees.add(new Employee("Alice", 35, 12000));
        employees.add(new Employee("Bob", 28, 9000));
        employees.add(new Employee("Charlie", 32, 15000));
        employees.add(new Employee("David", 25, 8000));
        employees.add(new Employee("Eve", 38, 13000));

        List<Employee> filteredEmployees = new ArrayList<>();
        for (Employee employee : employees) {
            if (employee.getAge() > 30 && employee.getSalary() > 10000) {
                filteredEmployees.add(employee);
            }
        }

        Collections.sort(filteredEmployees, Comparator.comparingDouble(Employee::getSalary).reversed());

        StringBuilder result = new StringBuilder();
        for (Employee employee : filteredEmployees) {
            result.append(employee.getName());
        }

        System.out.println(result.toString());
    }
}

Stream代码简洁性体现

  1. 链式调用:Stream通过链式调用将过滤、排序、映射和收集操作紧凑地连接在一起,无需中间变量存储中间结果,代码更简洁。例如employees.stream().filter(...).sorted(...).map(...).collect(...)
  2. 声明式编程:Stream更注重描述“做什么”,而不是“怎么做”。开发者只需指定过滤、排序和映射的规则,具体实现由Stream API负责,减少了底层循环和状态管理的代码。

与传统foreach代码结构和可读性差异

  1. 代码结构
    • Stream:结构上更扁平,操作按逻辑顺序链式排列,易于理解整个数据处理流程。
    • 传统foreach:需要多个独立的代码块分别完成过滤、排序和拼接操作,每个操作都需要手动管理中间变量和循环逻辑,代码结构相对复杂。
  2. 可读性
    • Stream:代码更接近自然语言描述,直观地表达了业务逻辑,如“筛选出符合条件的员工,按工资倒序排序,获取姓名并拼接”,可读性强。
    • 传统foreach:嵌套的循环和中间变量使得代码更关注具体实现细节,阅读时需要跟踪多个变量和操作,可读性较差。