Consider writing Groovy code to retrieve the transformed version of an element from a given collection such that transformed version of the element satisfies a given predicate.
Here’s a Groovy-only code snippet that uses only the features of Groovy.
(0..N).collect { e -> transform(e) }
.findResult([]) { e -> predicate(e) ? e : null }
Here’s a Groovy+Java code snippet that uses Java 8 streams.
IntStream.range(0, N)
.mapToObj { e -> transform(e) }
.filter { e -> predicate(e) }
.findAny()
.orElse([])
While the first snippet transforms (collect) every element in the source collection before executing findResult (staged execution), the second snippet executes the entire pipeline of functions for every element in the source collection. Consequently, the Groovy+Java snippet is more efficient as it stops transforming the elements as soon as the transformed version of an element is found.
In terms of parallelism, here’s the Groovy-only snippet parallelized using GPars.
GParsPool.withPool {
(0..N).collectParallel { e -> transform(e) }
.findResult([]) { e -> predicate(e) ? e : null }
}
While collect is parallelized (as collectParallel), findResult isn’t parallelized as it isn’t supported by GPars. Further, even if findResult was parallelized, it will only execute after collectParallel completes and, hence, the above observed inefficiency due to the staged execution will still persist.
In comparison, here’s the parallelized version of the Groovy+Java snippet.
IntStream.range(0, N)
.parallel().
.mapToObj { e -> transform(e) }
.filter { e -> predicate(e) }
.findAny()
.orElse([])
Unlike the parallelized Groovy-only snippet, each function in the pipeline is executed in parallel as its input becomes available. Hence, this will be more efficient than the parallelized Groovy-only snippet.
Few years ago, Groovy made Java groovier. With Java 8 streams, I think Java can make Groovy groovier.
That said, I am eager to see how will Groovy evolve to make Java groovier.
Top comments (0)