在Java中声明lambdas数组

时间:2017-12-05 09:30:27

标签: java lambda

我想创建一个lambda数组。问题是lambda可能彼此不同。例如:

if (caller.name() == classStr(MyCallerClass) )
{
     // MyCallerClass.myParmMethod(parameter);
}

现在,我如何声明一个既可以包含I0又可以包含I1的列表?

private interface I0 {
    int interface0(int a, int b);
}

private interface I1 {
    int interface1(double d);
}

显然List<Object> test = Arrays.asList( (int a, int b) -> a + b, (double d) -> d * 2 ); 不起作用。

4 个答案:

答案 0 :(得分:17)

您必须首先将lambda表达式分配给功能接口类型的变量。

否则编译器无法推断这些lambda表达式的类型。

I0 i0 = (int a, int b) -> a + b;
I1 i1 = (double d) -> (int) (d * 2);
List<Object> test = Arrays.asList(
    i0,
    i1
);

那就是说,我不确定将这些lambda表达式存储在List<Object>中是什么意思。如果不将它们转换回各个功能接口类型,则无法使用它们。

答案 1 :(得分:11)

您可以投射到相应的界面,如:

List<Object> test = Arrays.asList(
    (I0) (int a, int b) -> a + b,
    (I1) (double d) -> (int) (d * 2)
);

尽管这个更短,但我也会考虑Eran's answer它可能更容易理解(如果有更多功能)。而且我也看不到这种结构的用例...

它变得更短(不一定更好):

List<Object> test = Arrays.asList(
    (I0) (a, b) -> a + b,
    (I1) d -> (int) (d * 2)
);

答案 2 :(得分:2)

从我收集的内容来看,你正试图做这样的事情:

public static void main(String... args){
    List<Object> lambdas = Arrays.asList(
            (IntBinaryOperator) (int a, int b) -> a + b,
            (DoubleToIntFunction) (double d) -> (int)(d * 2)
    );
    for(int i=0;i<args.length;i++){
        // Apply lambdas.get(i) to args[i]
    }
}

但这个评论是一个非常重要的事情;你会如何实现它?

您可以在每轮检查中检查类型:

    for(int i=0;i<args.length;i++){
        if(lambdas.get(i) instanceof IntBinaryOperator){
            processedArgs[i] =
                    ((IntBinaryOperator) lambdas.get(i)).applyAsInt(MAGIC_NUMBER, Integer.parseInt(args[i]));
        }else{
            // All your other cases (may take a while)
        }
    }

验证每种可能的类型是一个巨大的痛苦,如果它依赖于位置,它只会运行一次,所以它有点过分。

我的建议取决于它是否是静态的(你的代码只在一个特定的参数集上运行)或动态的(它需要在所有类型的参数上运行)。对于静态代码,我只是在没有循环的情况下应用lambdas:

public static void main(String... args){
    processedArgs = new int[args.length];
    IntBinaryOperator op1 = (int a, int b) -> a + b;
    DoubleToIntFunction op2 =  (double d) -> (int)(d * 2);

    processedArgs[0] = op1.applyAsInt(MAGIC_NUMBER, Integer.parseInt(args[0]));
    processedArgs[1] = op2.applyAsInt(Double.parseDouble(args[1]));
}

对于动态解决方案,我建议切换到单一功能界面。我会满足最高要求,并在不需要的地方填写虚拟值:

public static void main(String... args){
    processedArgs = new int[args.length];
    List<DoubleBinaryOperator> ops = Arrays.asList(
            (a, b) -> a + b,
            (d, ignore) -> (d * 2)
    );
    for(int i=0;i<args.length;i++){
        processedArgs[i] = (int)ops.get(i).applyAsDouble(Double.parseDouble(args[i]), MAGIC_NUMBER);
    }
}

或者,最好是,如果你可以简化你的lambdas:

public static void main(String... args){
    processedArgs = new int[args.length];
    List<DoubleToIntFunction> ops = Arrays.asList(
            (d) -> (int)(d + MAGIC_NUMBER),
            (d) -> (int)(d * 2)
    );
    for(int i=0;i<args.length;i++){
        processedArgs[i] = ops.get(i).applyAsInt(Double.parseDouble(args[i]));
    }
}

我觉得你的解决方案最终没有任何一个复杂。只是想帮助你指明正确的方向。

答案 3 :(得分:0)

你可以让你的界面使用vararg输入:

public class NaryFunctionTest {

    interface NaryFunction<R extends Number> {
        R run(R... args);
    }

    @Test
    public void test() {
        NaryFunction<Integer> f1 = (Integer[] o) -> o[0] + o[1];
        NaryFunction<Double> f2 = (Double[] o) -> o[0] *2;
        List<NaryFunction<?>> test = Arrays.asList(
            f1,
            f2
        );
    }
}