如何从groovy调用Java的Stream.collect()?

qjp7pelc  于 2022-11-01  发布在  Java
关注(0)|答案(2)|浏览(278)

我对Scala的FP有一定的了解,我真的不喜欢Groovy对集合方法的命名。考虑到这一点,以及上面所做的一些架构选择,我发现在Groovy代码中使用Java 8 streams API(加上java.util.Optional)是一个很有吸引力的解决方案。
直到我碰到这个:

def finalCollection = [ 'some', 'items', 'really', 'not', 'important' ].stream()
        .map { aMethodReturningOptional(it) } //map String to Optional<Item>
        .flatMap { it.map(Stream.&of).orElseGet(Stream.&empty) } //convert to Stream<Item>
        .collect() //Groovy's collect, not stream's!

注意,它只在Groovy 2+ -treating closure as lambda中有效。让我感到困扰的是示例代码的最后一行。Groovy将调用转换为DefaultGroovyMethods.collect(),而不是我最初想要使用的Stream.collect()。当然,最后一行应该是:

.collect(Collectors.toList()) //Should call Java collect, but it doesn't

在我看来,调用某个扩展方法而不是类的本机“内置”方法是违反直觉的。
如何重写示例,以便调用Stream.collect()方法?

UPDATE:经过一番折腾,我发现了最初的问题。我编写了.collect{Collectors.toList()}(注意大括号),它当然调用了Groovy方法,而不是Java。注意:请记住在发布前进行四次检查...

bogh5gae

bogh5gae1#

使用Collectors.toList(),您可以得到您想要的结果:

import java.util.stream.*

class Item {
    final String name

    Item(name) {
        this.name = name
    }

    @Override
    String toString() {
        name
    }
}

def itemize(String name) {
    Optional.of(new Item(name))
}

def finalCollection = [ 'some', 'items', 'really', 'not', 'important' ].stream()
        .map { itemize(it) } //map String to Optional<Item>
        .flatMap { it.map(Stream.&of).orElseGet(Stream.&empty) } //convert to Stream<Item>
        .collect (Collectors.toList()) 

assert 'java.util.ArrayList' == finalCollection.class.name        
assert finalCollection.collect { it.name } == ['some', 'items', 'really', 'not', 'important']

无论如何,在groovy 2.4.5中,上面的代码也适用于

def finalCollection = [ 'some', 'items', 'really', 'not', 'important' ].stream()
        .map { itemize(it) } //map String to Optional<Item>
        .flatMap { it.map(Stream.&of).orElseGet(Stream.&empty) } //convert to Stream<Item>
        .collect()

使用groovy的collect的代码:
使用Close.IDENTITY作为转换器将每个项转换为新值,基本上返回从原始对象复制的项的列表。

5w9g7ksd

5w9g7ksd2#

Groovy 2.5.0和更高版本将toListtoSet方法添加为enhancements to Stream。不再需要使用Collectors.toList()

def finalCollection = [ 'some', 'items', 'really', 'not', 'important' ].stream()
        .map { it }
        .flatMap { it.map(Stream.&of).orElseGet(Stream.&empty) }
        .toList()

相关问题