gpt4 book ai didi

Java flatmap Iterator, Stream>> 到 Pair, Stream>

转载 作者:搜寻专家 更新时间:2023-10-30 19:41:15 29 4
gpt4 key购买 nike

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

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/

29 4 0