Java flatmap Iterator<Pair<Stream<A>, Stream<B>>> 到 Pair<Stream<A>, Stream<B>>

标签 java java-8 java-stream

我正在尝试实现具有以下签名的方法:

public static <A,B> Pair<Stream<A>, Stream<B>> flatten(Iterator<Pair<Stream<A>, Stream<B>>> iterator);

该方法的目标是将每种流类型展平为单个流并将输出包装成一对。我只有一个 Iterator(不是 Iterable)并且我不能改变方法签名,所以我必须在一次迭代中执行扁平化。

我目前最好的实现是

public static <A,B> Pair<Stream<A>, Stream<B>> flatten(Iterator<Pair<Stream<A>, Stream<B>> iterator) {
    Stream<A> aStream = Stream.empty();
    Stream<B> bStream = Stream.empty();
    while(iterator.hasNext()) {
        Pair<Stream<A>, Stream<B>> elm = iterator.next();
        aStream = Stream.concat(aStream, elm.first);
        bStream = Stream.concat(bStream, elm.second);
    }
    return Pair.of(aStream, bStream);
}

虽然这在技术上是正确的,但我对此并不十分满意,原因有二:

  1. Stream.concat warns against doing this kind of thing because it may lead to a StackOverflowError .
  2. 从风格上讲,如果可能的话,我宁愿它是纯函数式的,而不是必须遍历迭代器并在整个过程中重新分配流。

感觉像Stream#flatMap应该适合这里(在使用 Guava's Streams.stream(Iterator) 将输入 Iterator 转换为 Stream 之后,但由于中间的 Pair 类型,它似乎不起作用。

一个额外的要求是任何迭代器/流都可能非常大(例如,输入可以包含从一对非常大的流到许多一个项目流的任何地方)所以理想的解决方案不应该包含收集结果存入内存集合。

最佳答案

Guava 的 Streams.stream 并不神奇,它实际上在内部只是:

StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false);

所以可能不需要将其链接到您的方法,而您可以直接使用它。

您可以为此使用 Stream.Builder:

public static <A, B> Pair<Stream<A>, Stream<B>> flatten(Iterator<Pair<Stream<A>, Stream<B>>> iterator) {

    Stream.Builder<Stream<A>> builderA = Stream.builder();
    Stream.Builder<Stream<B>> builderB = Stream.builder();

    iterator.forEachRemaining(pair -> {
        builderA.add(pair.first);
        builderB.add(pair.second);
    });

    return Pair.of(builderA.build().flatMap(Function.identity()), builderB.build().flatMap(Function.identity()));
}

关于Java flatmap Iterator<Pair<Stream<A>, Stream<B>>> 到 Pair<Stream<A>, Stream<B>>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44735562/

相关文章:

java - 将两个 foreach 更改为一个流

java - 在单个流中组合 allMatch、noneMatch 和 anyMatch

java - 使用 java + selenium WebDriver 获取一些文本

java - 无法使用 AuthenticationAdmin API 身份验证创建 WSO2 Identity Server 5.1.0 的 java 客户端

java - Scala/Gradle 的 build.gradle 中包含什么

Java 8 List to EnumMap with sums

java - 如何解决 java.lang.ClassNotFoundException : org. aspectj.lang.ProceedingJoinPoint 异常?

java - 如何在java8中使用对象内的List属性进行groupingBy的groupingBy

Java 8 并行流并发分组

java - 使用与另一个列表的整个内容匹配的条目过滤列表的内容 Java 流