【问题标题】:java functional interface and lambda expressionjava函数式接口和lambda表达式
【发布时间】:2021-06-11 18:34:05
【问题描述】:

功能界面

import java.util.ArrayList;
public interface EmployeeAudit {

    public ArrayList<String> fetchEmployeeDetails (double salary);
}

在公共类 Main

public static EmployeeAudit findEmployee(){
    ArrayList<String> name=new ArrayList<>();
    return  (sal) -> {
        employeeMap.forEach((key,value) -> {
            if(value<=sal) 
                name.add(key);
        });
        return name;
    };
}    

在主函数中:

ArrayList<String> str = findEmployee().fetchEmployeeDetails(sal);

谁能帮我理解 sal 的值是如何转移到 findEmployee() 的,因为 findEmployee() 根据链接首先被调用。以及这些调用的工作原理。

【问题讨论】:

  • 如果您将 lambda 表达式替换为实现 EmployeeAudit 的匿名类,您能回答您自己的问题吗?
  • 始终避免在 lambda 中改变外部引用。更好的版本是:EmployeeAudit aud = sal -&gt; employeeMap.entrySet().stream().filter(e -&gt; sal &gt;= e.getValue()).map(Entry::getKey).collect(Collectors.toList());

标签: java lambda java-stream


【解决方案1】:

您的方法findEmployee() 实际上实例化 一个EmployeeAudit 对象。 EmployeeAudit 是一个接口,所以它需要定义它的方法,因为它们只有一个,它是一个函数接口,可以用 lambda 来完成,但它相当于

public static EmployeeAudit findEmployee() {
    ArrayList<String> name = new ArrayList<>();
    return new EmployeeAudit() {
        @Override
        public ArrayList<String> fetchEmployeeDetails(double sal) {
            employeeMap.forEach((key, value) -> {
                if (value <= sal)
                    name.add(key);
            });
            return name;
        }
    };
}

然后,在该实例上,您调用 fetchEmployeeDetails 方法,通过拆分代码可能更容易看到

EmployeeAudit ea = findEmployee();
ArrayList<String> str = ea.fetchEmployeeDetails(10);

您甚至可以想象创建实现EmployeeAudit 的类并非常轻松地使用

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

interface EmployeeAudit {
    ArrayList<String> fetchEmployeeDetails(double salary);
}

public class Test {
    static Map<String, Integer> employeeMap = new HashMap<>();

    public static void main(String[] args) {
        employeeMap.put("Jean", 10);
        employeeMap.put("Jean2", 100);
        employeeMap.put("Jean3", 100);
        EmployeeAudit ea = new EmployeeAuditImpl();
        ArrayList<String> str = ea.fetchEmployeeDetails(10);
        System.out.println(str);
    }

    static class EmployeeAuditImpl implements EmployeeAudit {
        @Override
        public ArrayList<String> fetchEmployeeDetails(double sal) {
            ArrayList<String> name = new ArrayList<>();
            employeeMap.forEach((key, value) -> {
                if (value <= sal)
                    name.add(key);
            });
            return name;
        }
    }
}

【讨论】:

  • 所以这种抽象方法的覆盖只发生在功能接口的情况下?所以,我理解你的回答。因为我们的 findEmployee() 具有接口 EmployeeAudit 的返回类型,因此它将创建它的一个实例,因此在这种情况下它的成员函数 fetchEmployeeDetails() 可以被访问。现在你能解释一下 findEmployee() 的 return 语句中的 lambda 函数如何覆盖 fetchEmployeeDetails() 吗?
  • @varun 了解“功能接口”,例如baeldung.com/java-8-functional-interfaces。任何方法都可以用 lambda 定义,但是如果接口只有一个方法,也可以用 lambda 定义:这是一个功能接口
【解决方案2】:

findEmployee() 返回一个匿名函数(实际上将EmployeeAudit 定义为一个函数,因为EmployeeAudit 是一个函数式接口)。

这个函数被定义为接受一个名为sal 的输入参数,但这不是你的主调用的sal:你可以将sal 重命名为findEmployee 中的其他任何东西,代码也可以正常工作。

内部sal 是一个参数的名称,您可以在任何其他常规函数中使用:

void someFunction(double sal) { ??? }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-10
    相关资源
    最近更新 更多