初始化 Lambda 的可运行数组(使用字符串 arg 并返回布尔值)和调用索引



我能够使用 lambda 的返回 void 并使用哈希表接收 0 个参数,请参见此处 -> 创建 lambda 二维数组

现在,我正在尝试创建一个Runnable[]数组,索引中包含 lambda,每个 lambda 都接受一个 String 参数并返回一个布尔值。

这是代码...

public class testLambdaWithPrimitiveType {
private final String[] numArray = {"One", "Two", "Three"};
private boolean numFound = false;
testLambdaWithPrimitiveType(String num){
setNumFound(num);
}
private void setNumFound(String num){
Runnable[] runnableNumArray = {
() -> isStringOne(num),
() -> isStringTwo(num),
() -> isStringThree(num)
};
for (int numChecked = 0; numChecked < runnableNumArray.length; numChecked++){
if (runnableNumArray[numChecked].run(num)){
this.numFound = true;
}
}
}
private boolean isNumFound(){return this.numFound;}
private boolean isStringOne(String num){
return num.equals(numArray[0]);
}
private boolean isStringTwo(String num){
return num.equals(numArray[1]);
}
private boolean isStringThree(String num){
return num.equals(numArray[2]);
}
public static void main(String[] args) {
testLambdaWithPrimitiveType objectOne = new testLambdaWithPrimitiveType("One");
testLambdaWithPrimitiveType objectTwo = new testLambdaWithPrimitiveType("Two");
testLambdaWithPrimitiveType objectThree = new testLambdaWithPrimitiveType("Three");
testLambdaWithPrimitiveType objectFour = new testLambdaWithPrimitiveType("Four");
System.out.println(objectFour.isNumFound()); // false
System.out.println(objectThree.isNumFound()); // true
System.out.println(objectTwo.isNumFound()); // true
System.out.println(objectOne.isNumFound()); // true
}
}

看起来数组被正确初始化了,但是当我尝试调用索引if (runnableNumArray[numChecked].run(num)){时,我收到编译错误。知道为什么会这样吗?

那是因为Runnable有方法void run(),没有参数,并且您正在尝试调用run(num)。由于已经从setNumFound()参数应用了num,因此只需使用run()调用 。

当然,这会导致第二个错误,即方法返回void,因此if (run())不起作用。

似乎你可能想要一个方法boolean xxx(String),所以Runnable替换为Predicate<String>,你可以用test(num)而不是run()来调用它。

这会导致编译错误Cannot create a generic array of Predicate<String>,因此您必须用List替换数组。

然后,可以改用方法引用。

private void setNumFound(String num){
List<Predicate<String>> runnableNumList = Arrays.asList(
this::isStringOne,
this::isStringTwo,
this::isStringThree
);
for (Predicate<String> runnableNum : runnableNumList){
if (runnableNum.test(num)){
this.numFound = true;
}
}
}

在 Java 语言中,Runnable实例不能有参数,有参数的 lambdaCallable实例。换句话说,你的问题不准确...您无法创建Runnable接受参数的数组,即使编译器(错误地)允许您这样做。

错误是Runnable接口具有带有签名的 run 方法,

public abstract void run()

但是,您正在尝试将参数传递给该运行方法。

runnableNumArray[numChecked].run( num )

删除num参数仍会给出错误。这是因为 run 方法返回void什么都不是(再看签名),但if语句需要一个boolean值来计算。

我不确定你想用这个lambda数组实现什么。如果您给我更多信息,我也许能够更正您的代码。就目前而言,目前尚不清楚您期望Runnables实现什么。

下面是使用 Callable 实例实现所需内容的示例。

private void setNumFound(String num) throws Exception {
Callable[] runnableNumArray = {
() -> isStringOne( num ),
() -> isStringTwo( num ),
() -> isStringThree( num )
};
for ( int numChecked = 0; numChecked < runnableNumArray.length; numChecked++ ){
if ( ( Boolean ) runnableNumArray[numChecked].call() ){
this.numFound = true;
}
}
}
private void setNumFound(String num){
boolean[] a = new boolean[1];
Runnable[] runnableNumArray = {
() -> a[0] = isStringOne(num),
() -> a[0] = isStringTwo(num),
() -> a[0] = isStringThree(num)
};
for (Runnable r : runnableNumArray ) {
r.run();
if ( a[0] ) {
this.numFound = true;
break; }
}
}

我重写了您的方法并将布尔变量添加为数组[1]。我认为,写错了,在一般情况下你会得到错误:"从 lambda 表达式引用的局部变量必须是最终的或实际上是最终的"——但它在 Java SE 8(build 31)中的工作。

最新更新