java 中的函数式编程:克隆与变异。是好是坏?

Functional programming in java: Cloning Vs Mutating. Good or bad?

变异:

"transformEmployeeNameToUpperCase" 将员工姓名转换为大写的函数。

List<Employee> employeesStartsWithDInUppercase1 = employees.stream()
            .filter(employee -> employee.getName().startsWith("D"))
            .map(Main::transformEmployeeNameToUpperCase)
            .collect(Collectors.toList());

public static Employee transformEmployeeNameToUpperCase(Employee employee){
    employee.setName(employee.getName().toUpperCase());
    return employee;
}

克隆:

"createEmployeeWithUpperCaseName" 对姓名大写的新员工起作用。

List<Employee> employeesStartsWithDInUppercase2 = employees.stream()
            .filter(employee -> employee.getName().startsWith("D"))
            .map(Main::createEmployeeWithUpperCaseName)
            .collect(Collectors.toList());


public static Employee createEmployeeWithUpperCaseName(Employee e){
    return new Employee( e.getId(), e.getName().toUpperCase(), e.getDesignation(), e.getAge());
}

Does "createEmployeeWithUpperCaseName" follow rule 1(above) as they say

是:员工没有被修改

In case of "transformEmployeeNameToUpperCase", does it follow rule 2(above)?

是的,尽管该规则使用了不正确的术语。它创建一个对象,而不是一个变量。您不能创建变量。

Is it good practice to use transformEmployeeNameToUpperCase way?

不,至少不是你这样做的方式。修改可变对象本身并没有什么坏处:它们是可变的是有原因的。但是 map() 操作不应该修改它的输入和 return 它。你在曲解它的目的。您的代码的未来 reader 不会期望映射操作改变其输入,因此您会让您的代码做意想不到的事情,从而导致错误 and/or 误解。这样做会更好:

employees.stream()
         .filter(employee -> employee.getName().startsWith("D"))
         .forEach(e -> e.setName(e.getName().toUpperCase()));

这样一来,就清楚了管道的作用是对列表的元素产生副作用。而且它也不会创建(可能)无用的列表副本。

同意@JB Nizet 的观点,但如果您不想更改原始对象但想将员工姓名更改为大写。使用对象克隆。

伪代码:

List<Employee> employeeWithUpperCaseName = employees.parallelStream()
                .filter(e -> e.getName().startsWith("D"))
                .map(x -> {
                    Employee s = null;
                    try {
                        s = (Employee) x.clone();
                        s.setName(x.getName().toUpperCase());
                    } catch (CloneNotSupportedException e) {
                        e.printStackTrace();
                    } finally {
                        return s;
                    }
                })
                .collect(Collectors.toList());

你可以写得更好