zoukankan      html  css  js  c++  java
  • 关于Java的惰性求值

    最近在学scala的时候,函数传参可以是传名参数,或者传值参数

    1.Scala中的传名参数是什么意思?lazy关键字有什么作用?

        Scala官方文档的定义是:传名参数 仅在被使用时触发实际参数的求值运算。 它们与 传值参数 正好相反。 要将一个参数变为传名参数,只需在它的类型前加上 =>。

    def calculate(input: => Int) = input * 37
    

    测试输出

      def main(args: Array[String]): Unit = {
    
        def input(): Int ={
          println("Initialized")
          1
        }
        lazy val i = input();
        println("begin for loop")
        for( a <- 1 to 3){
    
          val cal = calculate(i)
          println("cal:" + cal)
        }
    
      }
    

    output:

    begin for loop
    Initialized
    cal:37
    cal:37
    cal:37
    

        可以看到Initialized是在begin for loop后面打印出来,而且可以看到Initialized在三次循环调用中,只输出了一次,这是因为有缓存的,只会在第一次使用的时候进行初始化。

    2.在Java中如何实现类似的功能?

        其实单纯的惰性求值,是很好实现的,可以通过Java 8 中的 functional interface Supply来传递参数。

        public static Integer calculate(Supplier<Integer> s) {
            return s.get() * 37;
        }
    
        public static void main(String[] args) {
    
            Supplier<Integer> input = () -> {
                System.out.println("Initialized");
                return 1;
            };
    
            System.out.println("begin for loop");
            for (int i = 0; i < 3; i++) {
                Integer cal = calculate(input);
                System.out.println("cal:" + cal);
            }
    
    
        }
    

    output:

    begin for loop
    Initialized
    cal:37
    Initialized
    cal:37
    Initialized
    cal:37
    

        可以看到虽然实现了惰性求值,但是每次调用的时候supplier都会去计算一遍,这个时候可以用guava提供的MemoizingSupplier

        public static Integer calculate(Supplier<Integer> s) {
            return s.get() * 37;
        }
    
        public static void main(String[] args) {
    
            //这里返回的其实是MemoizingSupplier
            com.google.common.base.Supplier<Integer> input = Suppliers.memoize(() -> {
                System.out.println("Initialized");
                return 1;
            });
    
            System.out.println("begin for loop");
            for (int i = 0; i < 3; i++) {
                Integer cal = calculate(input);
                System.out.println("cal:" + cal);
            }
        }
    

    output:

    begin for loop
    Initialized
    cal:37
    cal:37
    cal:37
    

    通过输出可以看到,实现的效果和scala是一样的,做到了惰性求值,且有缓存,只会被执行一次。

  • 相关阅读:
    ORACLE NOLOGGING研究
    由2013星光大道总决赛同步程序猿怎样成功?
    configure: error: mysql configure failed. Please check config.log for more information.
    The 2014 ACM-ICPC Asia Mudanjiang Regional Contest(2014牡丹江区域赛)
    about service in android
    极客标签互动课程系列 - Javascript生成SVG动画素描特效
    sql -- 移除数据中的换行符和回车符
    前端project师必需知识点
    spring装配集合
    【java项目实践】具体解释Ajax工作原理以及实现异步验证username是否存在+源代码下载(java版)
  • 原文地址:https://www.cnblogs.com/IC1101/p/15153989.html
Copyright © 2011-2022 走看看