Я пытаюсь реализовать метод со следующей сигнатурой:
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);
}
Но пока это технически правильно, я не очень доволен этим по двум причинам:
- Stream.concat предупреждает об этом, потому что это может привести к StackOverflowError.
- Стилистически я предпочел бы, чтобы это было чисто функционально, если возможно, вместо того, чтобы перебирать итератор и повторно назначать потоки.
Кажется, что Stream # flatMap должен быть здесь подходящим (после преобразования входного Iterator в Stream с использованием Guava Streams.stream(Iterator), но, похоже, он не работает из-за типа пары в середине.
Еще одно требование состоит в том, что любой из итераторов/потоков может быть очень большим (вход может содержать где угодно от одной пары чрезвычайно больших потоков ко многим потокам одного элемента, например), поэтому решения в идеале не должны содержать сбор результаты в коллекции в памяти.