给定一个Java函数,如何更新一个函数值?

时间:2019-02-20 14:12:12

标签: java functional-programming

如果我在OCaml中具有函数f,则只需输入

let f x = if x=1 then 42 else f x

如果这不能掩盖f的旧定义,那正是我想要的。现在,我正在寻找Java中的等效项,但附加的约束是Function f 中的引用已更新。我可以创建一个Function对象

Function<Integer, Integer> f = new Function<>() {
    @Override
    public Integer apply(Integer integer) {
        return integer+1;
    }
};;

现在可以通过

定义一个新的Function
Function<Integer, Integer> g = new Function<>() {
    @Override
    public Integer apply(Integer integer) {
        if (integer==1)
            return 42;
        else
            return f.apply(integer);
    }
};;

但是,只有在f被声明为final或实际上是final的情况下,这才起作用。因此,我无法通过f = g;更改引用。我该怎么办?

编辑:为明确起见,我必须设置f使其引用使用旧Function的{​​{1}}如之前所提到的。所需的代码如下所示:

Function f

4 个答案:

答案 0 :(得分:2)

实际上,您不能这样做。正如您已经说过的,在函数接口中使用的变量必须是最终的(或实际上是最终的)。您可以做的是包装引用,例如使用AtomicReference。然后,您将得到如下内容:

    final AtomicReference<Function<Integer, Integer>> ref = new AtomicReference<>();

    Function<Integer, Integer> f = new Function<>() {
        @Override
        public Integer apply(Integer integer) {
            return integer+1;
        }
    };

    ref.set(f);

    Function<Integer, Integer> g = new Function<>() {
        @Override
        public Integer apply(Integer integer) {
            if (integer==1)
                return 42;
            else
                return f.apply(integer);
        }
    };

    ref.set(g);

该功能将通过ref.get()提供

答案 1 :(得分:1)

您可以通过将第一个函数嵌套在第二个函数中来摆脱本地作用域中的一个变量。除非您需要两个变量(不太可能,并且在这种情况下使用A.Bitner提出的原子引用解决方案是可行的),否则这应该起作用:

Function<Integer, Integer> f = new Function<Integer, Integer>() {

    //this can even be made a local variable of f.apply() 
    final Function<Integer, Integer> innerFunction = new Function<Integer, Integer>() {
        @Override
        public Integer apply(Integer integer) {
            return integer + 1;
        }
    };

    @Override
    public Integer apply(Integer integer) {
        if (integer == 1)
            return 42;
        else
            return innerFunction.apply(integer);
    }
};

以及等效的lambda表达式:

Function<Integer, Integer> f = i -> {
    Function<Integer, Integer> f1 = e -> e + 1;
    return i == 1 ? 42 : f1.apply(i);
};

答案 2 :(得分:1)

我不确定是否完全了解OP想要做什么,但也许可以扩展Function<Integer,Integer>并添加af(Function<Integer,Integer>作为具有setter和getter的扩展类的属性,可以解决以下问题:变量访问并能够更改f)的值

注意:我使用了public属性,而不是setter和getter ...

public class TestClass{

     public static void main(String []args){
        Function<Integer, Integer> f = new Function<Integer,Integer>() {
            @Override
            public Integer apply(Integer integer) {
                return integer+1;
            }
        };

        MyFunction g = new MyFunction();
        g.f = f;

        g.apply(1);
     }



     public static class MyFunction implements Function<Integer,Integer>{

         public Function<Integer,Integer> f;

         @Override
         public Integer apply(Integer integer){
             if (integer==1)
                return 42;
             else
               return f.apply(integer);
         }

     }
}

答案 3 :(得分:0)

可能的解决方案是使用List

ArrayList<Function<Integer, Integer>> fList = new ArrayList<>();
fList.add(i -> i+1);
Function<Integer, Integer> g = new Function<>(){
    final Function<Integer, Integer> fPre = fList.get(fList.size()-1);
    @Override
    public Integer apply(Integer integer){
        if (integer == 1)
            return 42;
        else
            return fPre.apply(integer);
    }
}
fList.add(g);

然后在定义之外需要f = fList.get(fList.size()-1)时使用f

这个想法是,我们将所有f都存储在List中,从最旧到最新。