groovy - Groovy中链式功能方法的惰性评估

标签 groovy functional-programming closures java-8 lazy-evaluation

我在Java中所见

Java 8允许对链接函数进行延迟评估,以避免性能损失。

例如,我可以拥有一个值列表,并像这样处理它:

someList.stream()
        .filter( v -> v > 0)
        .map( v -> v * 4)
        .filter( v -> v < 100)
        .findFirst();

我将多个闭包传递给流上调用的方法,以处理集合中的值,然后仅获取第一个。

看起来代码似乎必须遍历整个集合,对其进行过滤,然后遍历整个结果并应用一些逻辑,然后再次过滤整个结果,最后仅获取一个元素。

实际上,编译器以更智能的方式进行处理,并优化了所需的迭代次数。

这是可能的,因为直到调用findFirst才进行任何实际处理。通过这种方式,编译器知道我要实现的目标,并且可以找出如何高效地实现目标。

查看此video of a presentation by Venkat Subramaniam以获得更详细的说明。

我想在Groovy中做什么

在回答question about Groovy here on StackOverflow时,我想出了一种方法来执行OP试图以更具可读性的方式完成的任务。我不建议这样做,因为这意味着性能下降。

这是示例:
collectionOfSomeStrings.inject([]) { list, conf ->  if (conf.contains('homepage')) { list } else { list << conf.trim() } }

从语义上讲,这可以重写为
collectionOfSomeStrings.grep{ !it.contains('homepage')}.collect{ it.trim() }

我发现它更容易理解,但是可读性是有代价的。此代码需要传递原始集合,并需要对grep的结果进行另一次迭代。这不理想。

看起来GDK的grepcollectfindAll方法看起来像Java 8的stream API中的方法一样被延迟评估。有什么办法让他们表现得这样吗?在Groovy中我可以使用任何替代库吗?

我想可能可以在Groovy中以某种方式使用Java 8并具有此功能。我希望对这些细节进行解释,但是理想情况下,我希望能够使用较旧版本的Java来做到这一点。

我找到了way to combine closures,但这并不是我真正想要的。我不仅要链接闭包本身,还要链接传递给它们的函数。

对Groovy和Streams进行谷歌搜索通常会产生与I/O相关的结果。通过搜索惰性评估,功能和Groovy,我还没有发现任何有趣的东西。

最佳答案

以cfrick的评论为例,将建议添加为答案:

@Grab( 'com.bloidonia:groovy-stream:0.8.1' )
import groovy.stream.Stream

List integers = [ -1, 1, 2, 3, 4 ]

//.first() or .last() whatever is needed
Stream.from integers filter{ it > 0 } map{ it * 4 } filter{ it < 15 }.collect()

蒂姆,我仍然知道你几个夏天前做了什么。 ;-)

关于groovy - Groovy中链式功能方法的惰性评估,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27024454/

相关文章:

java - spock - 模拟静态方法不起作用

haskell - 我对Euler#92计划的尝试太慢

从 R 中的 apply() 函数返回多个值

php - 为什么我不能在非匿名函数中使用 'use'?

multithreading - 使用Groovy的GPar,何时需要使用collectParallel()进行显式同步?

flash - 柔性 socket 连接

调用eachParallel() 时的 Groovy (GPars) 和 MissingMethodException

javascript - 聚合和转换对象数组

javascript - 当您真正想要产生副作用时, "functional programming"背后的哲学是什么?

javascript - 闭包(let 关键字)- Javascript