java - 如何将字符串转换为 lambda 表达式?

标签 java lambda java-8

我想了想,想出了一个有趣的问题,假设我们有一个配置(输入)文件:

x -> x + 1
x -> x * 2
x -> x * x
x -> -x

此外,我们还有一个 Integer 列表:

List<Integer> list = new ArrayList<>();
list.addAll(Arrays.toList(1, 2, 3, 4, 5));

有没有办法将 Strings(x -> x + 1 等)转换为代表 a 的 Objects lambda 表达式?然后可以用作:

Object lambda = getLambdaFromString("x -> x + 1");
if (lambda.getClass().equals(IntFunction.class) {
    list.stream().forEach()
        .mapToInt(x -> x)
        .map(x -> ((IntFunction)lambda).applyAsInt(x))
        .forEach(System.out::println);
}

我该如何编写这样的方法getLambdaFromString

  • 我可以从 JDK/JRE 中重用一些东西吗?
  • 我需要自己写吗?
  • 是否可以将 Object lambda 缩小为仅捕获 lambda 的其他内容?

最佳答案

Marko 对这个问题的评论是正确的。您无法从文件中读取裸 Java lambda 表达式,因为没有上下文提供的目标类型就不会定义这样的表达式。例如,考虑以下方法声明:

void method1(BiFunction<String,String,String> f) { ... }
void method2(BiFunction<Integer,Integer,Integer> f) { ... }

那么在下面的代码中,

method1((x, y) -> x + y);
method2((x, y) -> x + y);

两个 lambda 表达式 (x, y) -> x + y意思是完全不同的东西。对于方法 1,+运算符是字符串连接,但是对于method2来说,是整数加法。

这离您的问题有点远,但您可以使用动态语言读取和评估 lambda 或函数表达式。在 Java 8 中有 Nashorn JavaScript 引擎。因此,您可以使用从 Java 调用的 Nashorn 读取和评估 JavaScript 函数,而不是尝试读取 Java lambda 表达式的求值。

以下代码采用 arg[0] 中的一个函数并将其应用于每个后续函数,并打印结果:

import java.util.function.Function;
import javax.script.*;

public class ScriptFunction {
    public static void main(String[] args) throws Exception {
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
        @SuppressWarnings("unchecked")
        Function<Object,Object> f = (Function<Object,Object>)engine.eval(
            String.format("new java.util.function.Function(%s)", args[0]));
        for (int i = 1; i < args.length; i++) {
            System.out.println(f.apply(args[i]));
        }
    }
}

例如运行命令

java ScriptFunction 'function(x) 3 * x + 1' 17 23 47

给出结果

52.0
70.0
142.0

new java.util.function.Function 内部的函数字符串的换行为了在 Nashorn 的 JavaScript 函数概念和 Java 的 Function 接口(interface)之间创建适配器,这是必需的。 (可能有更好的方法,但我不知道。) eval 的返回值的转换至Function<Object,Object>导致未经检查的强制转换警告,我认为这是不可避免的,因为这是 JavaScript(动态类型语言)和 Java(静态类型)之间的边界。最后,没有进行错误检查。我敢肯定,如果违反某些假设,例如第一个参数实际上并不代表 JavaScript 函数,这会以各种令人讨厌的方式爆发。

不过,如果您需要评估从文件中读取的表达式或函数,您可能会发现此技术很有用。

关于java - 如何将字符串转换为 lambda 表达式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22207447/

相关文章:

java.lang.RuntimeException : Unable to destroy activity {com. xxxxx/com.xxxxx.MapsActivity}:

java - 授权 header 在基本身份验证 JAVA 中不起作用

Java 8 : how to use lambda expressions on JoinRowSets?

java - 嵌套列表java 8流之间的交集

java - 调用 repaint() 时 JPanel 的奇怪行为

Java - 获取缓冲图像的屏幕位置

C# 语法 lambda 带大括号

c# lambda 表达式 if condition inside a where

java - 如何将这 2 个 lambda 表达式合并到一个 GroupBy 调用中?

java - 如何使用 java 8 流过滤具有两个列表的对象?