Welcome 微信登录

首页 / 软件开发 / JAVA / Java中的惰性计算简介

Java中的惰性计算简介2013-09-19 Neal Ford 惰性计算(尽可能延迟表达式求值)是许多函数式编程语言的特性。惰性集合在需要时提供其元素,无需预先计算它们 ,这带来了一些好处。首先,您可以将耗时的计算推迟到绝对需要的时候。其次,您可以创造无限个集合,只要它们继续收 到请求,就会继续提供元素。第三,map 和 filter 等函数的惰性使用让您能够得到更高效的代码。Java 并没有为惰性提 供原生支持,但一些框架和后继语言支持这种惰性,我会在本期和下期文章中探讨它们。

假定使用此伪代码片段来 打印列表的长度:

print length([2+1, 3*2, 1/0, 5-4])

如果您尝试执行此代码,结果会因为代码的编程语言类型的不同而有所不同:严格或不严格(也被称为惰性)。在严格 的编程语言中,执行(或编译)此代码产生一个 DivByZero 异常,原因是列表的第三个元素。在不严格的语言中,其结果 是 4,它准确地报告了列表中的项目数。毕竟,我调用的方法是 length(),而不是 lengthAndThrowExceptionWhenDivByZero()!Haskell 是为数不多的仍在使用的不严格语言。可惜的是,Java 不支持不严 格的计算,但您仍然可以在 Java 中使用惰性的概念。

在 Java 中的惰性迭代器

Java 缺乏对惰性集合的原 生支持,但这并不意味着您不能使用 Iterator 模拟一个惰性集合。在本系列的前几篇文章中,我使用了一个简单的素数算 法来说明函数式概念。我会在 上期文章 中介绍的优化类的基础上展开本文的讨论,同时提供清单 1 中展示的增强:

清单 1. 确定素数的简单算法

import java.util.HashSet;import java.util.Set;import static java.lang.Math.sqrt;public class Prime {public static boolean isFactor(int potential, int number) {return number % potential == 0;}public static Set<Integer> getFactors(int number) {Set<Integer> factors = new HashSet<Integer>();factors.add(1);factors.add(number);for (int i = 2; i < sqrt(number) + 1; i++)if (isFactor(i, number)) {factors.add(i);factors.add(number / i);}return factors;}public static int sumFactors(int number) {int sum = 0;for (int i : getFactors(number))sum += i;return sum;}public static boolean isPrime(int number) {return number == 2 || sumFactors(number) == number + 1;}public static Integer nextPrimeFrom(int lastPrime) {lastPrime++;while (! isPrime(lastPrime)) lastPrime++;return lastPrime;}}
前面的一期文章 详细讨论了这个类是如何确定某个整数是否是素数的细节。在 清单 1 中,我添加了 nextPrimeFrom() 方法,根据输入的参数生成下一个素数。该方法在本文即将出现的示例中发挥了重要的作用。

一 般情况下,开发人员认为迭代器会使用集合作为后备存储,但是支持 Iterator 接口的任何集合都符合这个条件。因此,我 可以创建一个素数的无限迭代器,如清单 2 所示:

清单 2. 创建一个惰性迭代器

public class PrimeIterator implements Iterator<Integer> {private int lastPrime = 1;public boolean hasNext() {return true;}public Integer next() {return lastPrime = Prime.nextPrimeFrom(lastPrime);}public void remove() { throw new RuntimeException("Can"t change the fundamental nature of the universe!");}}