Last updated at Mon, 06 Nov 2017 21:35:56 GMT

概述

“I will always choose a lazy person to do a difficult job. Because he will find an easy way to do it” – Bill Gates

惰性求值是 评估策略 which delays the evaluation of an expression until its value is needed. The opposite of this is eager evaluation, where an expression is evaluated as soon as it is bound to a variable.[维基百科]

Like most imperative programming languages, Java evaluates a method’s arguments eagerly, but we should consider a lazy alternative for scenarios where we can boost performance, for example avoiding a needless expensive computation.

We will see through an example how easy is to implement lazy evaluation exploiting 功能接口Lambda表达式.

例子

Let’s suppose we have the following expensive computation:

static boolean compute(String str) {
    系统.出.println(“执行...");
    // expensive computation here
    返回str.包含(a);
}

即时抓取

Consider the following function which takes two booleans 和 returns “match” if both are true, otherwise returns “不兼容的!”.

static String eagerMatch(boolean b1, boolean b2) {
    返回b1 && b2 ? match:不兼容!";
}

public static void main(String [] args) {
    系统.出.print(eagerMatch(compute("bb"), compute("aa")));
} 

Running this program produces the following 出put:

执行...
执行...
不兼容的! 

懒惰的评价

Let’s implement a lazy version using the Supplier 功能界面.

Java规范、接口

  • Represents a supplier of results.
  • There is no requirement that a new or distinct result be returned each time the supplier is invoked.
  • 这是一个 功能界面 其函数方法为 get ().

Basically it represents a function that takes no arguments 和 returns a value. In this case we use a supplier of boolean to create a lazy match equivalent to eager match:

static String lazyMatch(Supplier a, Supplier b) {
    返回一个.get () && b.get () ? match:不兼容!";
}

Because Supplier is a 功能界面, it can be used as the assignment of a lambda expression:

public static void main(String [] args) {
    系统.出.println(lazyMatch(() -> compute("bb"), () -> compute("aa")));
} 

The 出put of running this program for no match:

执行...
不兼容的!

Two important things to notice in running this example:

  • compute is executed when the functional method get is invoked.
  • && operator exhibits “short-circuiting”, which means that the second oper和 is evaluated only if needed.

The combination of lazy argument 和 oper和 evaluation allows this program to avoid the expensive execution in compute(“aa”).

结论

We have seen how simple it is to convert an eagerly evaluated method into a lazy evaluated one. Although the lazy call is a bit more involved compared to the eager call, the performance gains payoff the cosmetic drawback. 话虽如此, do not use lazy strategy everywhere, but do use it for cases where there are clear signs of performance improvements, i.e. :

The next blog will show how to move from an imperative style to a declarative style exploiting the lazy nature of streams.