ski*_*iwi 33 java lambda java-8
我想了一下并提出了一个有趣的问题,假设我们有一个配置(输入)文件:
x -> x + 1
x -> x * 2
x -> x * x
x -> -x
Run Code Online (Sandbox Code Playgroud)
此外,我们有一个Integers 列表:
List<Integer> list = new ArrayList<>();
list.addAll(Arrays.toList(1, 2, 3, 4, 5));
Run Code Online (Sandbox Code Playgroud)
有没有办法将Strings(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);
}
Run Code Online (Sandbox Code Playgroud)
我怎么写这样的方法getLambdaFromString?
Object lambda到仅捕获lambda的其他东西?Stu*_*rks 31
马可对这个问题的评论是正确的.您无法从文件中读取裸Java lambda表达式,因为如果没有上下文提供的目标类型,则不会定义此类表达式.例如,请考虑以下方法声明:
void method1(BiFunction<String,String,String> f) { ... }
void method2(BiFunction<Integer,Integer,Integer> f) { ... }
Run Code Online (Sandbox Code Playgroud)
然后在下面的代码中,
method1((x, y) -> x + y);
method2((x, y) -> x + y);
Run Code Online (Sandbox Code Playgroud)
两个lambda表达式(x, y) -> x + y意味着完全不同的东西.对于method1,+运算符是字符串连接,但对于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]));
}
}
}
Run Code Online (Sandbox Code Playgroud)
例如,运行命令
java ScriptFunction 'function(x) 3 * x + 1' 17 23 47
Run Code Online (Sandbox Code Playgroud)
给出结果
52.0
70.0
142.0
Run Code Online (Sandbox Code Playgroud)
new java.util.function.Function为了在Nashorn的JavaScript函数概念和Java的Function接口之间创建一个适配器,必须包含函数字符串.(可能有更好的方法,但我不知道一个.)返回值的eval转换Function<Object,Object>导致未经检查的强制转换警告,这是不可避免的,我认为,因为这是JavaScript之间的边界,动态-typed语言和Java,它是静态类型的.最后,没有进行错误检查.如果某些假设被违反,我肯定会以各种令人讨厌的方式爆炸,例如第一个参数实际上并不代表JavaScript函数.
但是,如果您需要评估从文件读取的表达式或函数,您可能会发现此技术很有用.
Paw*_*żyk 16
我相信在大多数情况下,使用Stuart答案中提到的Nashorn JavaScript引擎是最佳选择.但是,如果由于某种原因,我希望保持在Java世界中,我最近创建了LambdaFromString库,它在运行时将String代码转换为lambda.
使用该库时,执行问题中指定的代码如下所示:
List<Integer> list = new ArrayList<>();
list.addAll(Arrays.asList(1, 2, 3, 4, 5));
LambdaFactory lambdaFactory = LambdaFactory.get();
Function<Integer, Integer> lambda = lambdaFactory
.createLambda("x -> x + 1", new TypeReference<Function<Integer, Integer>>() {});
list.stream().map(lambda).forEach(System.out::println); //prints 2 to 6
Run Code Online (Sandbox Code Playgroud)
唯一不同的是,必须知道lambda的类型并将其传递给库,以便编译器知道在此上下文中"+"的含义.
| 归档时间: |
|
| 查看次数: |
13447 次 |
| 最近记录: |