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

时间:2017-05-18 18:22:11

标签: java arrays lambda runnable

我能够使用lambda的返回void并使用哈希表获取0 args,请参阅此处 - > Create lambda two dimensional array

现在,我正在尝试创建一个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)){时,出现编译错误。知道为什么会这样吗?

2 个答案:

答案 0 :(得分:1)

在Java语言中,Runnable实例不能有参数,而具有参数的lambda则是Callable个实例。换句话说,你的问题是不准确的......你不能创建带有参数的Runnable数组,即使编译器(错误地)允许你这样做。

错误是Runnable接口有一个带签名的run方法

public abstract void run()

然而,您正在尝试将参数传递给该run方法。

runnableNumArray[numChecked].run( num )

删除num参数仍会出错。这是因为run方法返回void nothing (再次查看签名),但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;
    }
  }
}

答案 1 :(得分:1)

这是因为Runnable有方法void run(),没有参数,而您正试图致电run(num)。由于已num参数已应用setNumFound(),因此只需使用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;
        }
    }
}