【问题标题】:How we I achieve add(4)(10)(20)(3)(1).total using Java Function?我们如何使用 Java 函数实现 add(4)(10)(20)(3)(1).total?
【发布时间】:2019-04-07 15:03:56
【问题描述】:

我正在学习使用,

java.util.function.Function

我写了一段代码,它使用java函数给自己加4,

代码如下,

public class Test01 {

    public static void main(String[] args) {
        Function<Integer,Integer> addFunction = new Function<Integer,Integer>() {
            private int total = 0; 
            public Integer apply(Integer value) {               
                this.total += value; 
                return this.total;
            }
        };



        int finalTotal = addFunction.andThen(addFunction)
                                    .andThen(addFunction)
                                    .andThen(addFunction)
                                    .apply(4);

        System.out.println(finalTotal);
    }

}

当我运行上面的代码时,我得到的输出是

32

我怎样才能实现我在 javaScript 中所做的事情,如下所示,

var fn19 = function(){

        var addNum = function(num){

            var fn = function(num2){
                fn.sum += num2;             
                return fn;
            };

            fn.sum = num;   
            return fn;
        };

        print("addNum(3)(4)(3)(10) ==>  "+addNum(3)(4)(3)(10).sum); 
};

fn19();  

上面代码的输出是

addNum(3)(4)(3)(10) ==> 20

我可以有相同类型的 java 函数调用吗?我可以在其中传递尽可能多的数字参数,并且 addFunction 将添加这些数字。

【问题讨论】:

  • 不太容易,因为 Java 是一种类型化语言。为了能够访问一个字段,您需要定义一个实现Function&lt;...&gt; 的类型,但允许您访问该接口合同以外的其他内容。此外,您似乎在 Javascript 代码中使用了 Function&lt;Integer,Function&lt;Integer&gt;&gt; 的等价物,而不是 Functyon&lt;Integer,Integer&gt;
  • 这和 RxJava 有什么关系?

标签: java java-8 functional-programming functional-java


【解决方案1】:

一个尽可能接近您的 JavaScript 代码的示例

class QuestionableConstruct {
    int sum;
    QuestionableConstruct add(int num2) {
        sum += num2;
        return this;
    }
}
Runnable fn19 = () -> {
    IntFunction<QuestionableConstruct> addNum = num -> {
        QuestionableConstruct fn = new QuestionableConstruct();
        fn.sum = num;   
        return fn;
    };
    System.out.println("addNum(3)(4)(3)(10)==> "+addNum.apply(3).add(4).add(3).add(10).sum);
};
fn19.run();

一个更像 Java 的解决方案是

interface Add {
    int sum();
    default Add add(int num) {
        int sum = sum() + num;
        return () -> sum;
    }
    static Add num(int num) {
        return () -> num;
    }
}

可用作

System.out.println("addNum(3)(4)(3)(10) ==>  "+Add.num(3).add(4).add(3).add(10).sum());

与 JavaScript 构造不同,它使用真正的不可变函数。考虑

Add a = Add.num(1).add(2).add(3);
System.out.println("1+2+3+4+5 = "+a.add(4).add(5).sum());
System.out.println("1+2+3+10+20 = "+a.add(10).add(20).sum());

运行顺畅,不受干扰。

当然,如果您只想对可变数量的项目求和,请使用

System.out.println("addNum(3)(4)(3)(10) ==>  "+IntStream.of(3, 4, 3, 10).sum()); 

或者如果你想要一个可变的累加器,使用

System.out.println("addNum(3)(4)(3)(10) ==>  "+
    IntStream.builder().add(3).add(4).add(3).add(10).build().sum());

允许保留构建器并传递它。

【讨论】:

    【解决方案2】:

    您不能在 Java 中完全做到这一点,您要寻找的是 reducing 值流。

    换句话说:这里“真正的”函数式解决方案不是使用多个参数调用一个方法。您宁愿将值放在某个列表中,然后通过对元素应用函数来定义“累积”该列表内容的函数。

    有关示例,请参阅 here

    【讨论】:

      【解决方案3】:

      您在 JavaScript 世界中描述的技术是利用闭包。

      这是 JavaScript 中函数作为一等公民的一个很好的副作用。这是一种将函数与封闭范围内的数据相关联,然后能够在不丢失内部上下文的情况下传递此关联的方法。最常见/最简单的用途是缓存(它的正式名称是 memoisation)。

      您需要 Java 中的函数(方法)是第一类,但这样做是多余的,因为类在设计上是一个关联数据和方法的实体,因此在这种情况下,闭包的整个概念是多余的。

      【讨论】:

        猜你喜欢
        • 2015-04-07
        • 2022-11-18
        • 2012-01-12
        • 2022-11-30
        • 2019-11-03
        • 2018-09-10
        • 2022-11-18
        • 1970-01-01
        • 2020-09-27
        相关资源
        最近更新 更多