如何将字符串转换为lambda表达式?
我想了一下,想到了一个有趣的问题,假设我们有一个配置(输入)文件,其中:
x -> x + 1x -> x * 2
x -> x * x
x -> -x
此外,我们还有Integer
s 的列表:
List<Integer> list = new ArrayList<>();list.addAll(Arrays.toList(1, 2, 3, 4, 5));
有没有办法将String
s(x -> x + 1
等)转换为Object
代表lambda表达式的s?然后可以用作:
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的其他内容?
回答:
马可对这个问题的评论是正确的。您无法从文件中读取裸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
含义
。对于method1,+
运算符为字符串连接,但对于method2,则表示整数加法。
这有点偏离您的问题,但是您可以使用动态语言阅读和评估lambda或函数表达式。在Java 8中,有Nashorn
JavaScript引擎。因此,您可以尝试使用Nashorn(从Java调用)来读取和评估 函数,而不必尝试读取评估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.070.0
142.0
new
java.util.function.Function为了在Nashorn的JavaScript函数概念和Java的Function接口之间创建一个适配器,必须在函数字符串内部进行包装。(也许有更好的方法,但我不知道。)将返回值强制转换为eval
to会Function<Object,Object>
导致未经检查的强制转换警告,我认为这是不可避免的,因为这是JavaScript(动态)类型语言和Java(静态类型)。最后,不执行任何错误检查。我敢肯定,如果违反某些假设(例如第一个参数实际上并不代表JavaScript函数),那么它将以各种讨厌的方式爆炸。
但是,如果需要评估从文件读取的表达式或函数,则可能会发现此技术很有用。
以上是 如何将字符串转换为lambda表达式? 的全部内容, 来源链接: utcz.com/qa/421578.html