在Java 8中,如何从Stream <! - 获取Stream <t>?扩展Collection <T - >&gt;?</t>

时间:2014-12-25 05:13:42

标签: java collections java-8 java-stream

在Java 8中,使用包java.util.functionjava.util.stream以及新语言功能 lambda 方法引用,什么是将Stream<Collection<T>>转换为Stream<T>的最佳方式?

这是我迄今为止找到的解决方案的示例,但我对此并不满意。为了从Stream<T>创建Stream<Collection<T>>,我使用collect().stream()与中间HashSet(我的CollectionSet)。< / p>

import java.security.Provider;
import java.util.HashSet;
import static java.lang.System.out;
import static java.security.Security.getProviders;
import static java.security.Provider.Service;
import static java.util.Arrays.stream;

public class ListMessageDigests {
    public static void main(final String... args) {
        stream(getProviders())
            .map(Provider::getServices)
            .collect(HashSet<Service>::new, HashSet::addAll, HashSet::addAll)
            .stream()
            .filter(service -> "MessageDigest".equals(service.getType()))
            .map(Service::getAlgorithm)
            .sorted()
            .forEach(out::println);
    }   
}   

是否有更优雅的方式将Stream<Collection<T>>转换为Stream<T>就像本例中的Stream<Set<Service>>一样Stream<Service>?我对使用中级HashSet.collect().stream()感到不满意,这对我来说很复杂。

P.S .: 我知道我可以简单地做到这一点:

import static java.security.Security.getAlgorithms;
public class ListMessageDigests {
    public static void main(final String... args) {
        getAlgorithms("MessageDigest")
            .forEach(out::println);
    }
}

我只使用getProviders()getServices快速构建Stream<Set<Service>>Stream<Collection<T>>来展示问题。

1 个答案:

答案 0 :(得分:9)

您可以将flatMapCollection#stream

一起使用
<T> Stream<T> flatten(Stream<? extends Collection<? extends T>> stream){
    return stream.flatMap(Collection::stream);
}

最终代码如下所示:

import static java.lang.System.out;
import static java.security.Provider.Service;
import static java.security.Security.getProviders;
import static java.util.Arrays.stream;

public class ListMessageDigests {
    public static void main(final String... args) {
        stream(getProviders())
            .flatMap(p -> p.getServices().stream())
            .distinct()
            .filter(service -> "MessageDigest".equals(service.getType()))
            .map(Service::getAlgorithm)
            .sorted()
            .forEach(out::println);
    }
}

请注意,如果不调用distinct,这可能不会产生与您的示例具有完全相同元素的流,因为收集到集合将删除重复项(如果有)。