объединить потоки для создания чередующейся последовательности с использованием лямбда или Stream API

У меня есть некоторый код, который возвращает поток, как и предполагалось, но, возможно, его можно заменить каким-либо типом лямбда-операции или операции stream() вместо исчерпания итераторов в цикле while?

Это просто метод, который чередует элементы из потоков first и second и останавливается, когда в одном из них заканчиваются элементы.

public static <T>Stream<T> alternatingSequence(Stream<T> first, Stream<T> second){
        Iterator<T> iteratorFirst = first.iterator();
        Iterator<T> iteratorSecond = second.iterator();
        Stream<T> resultStream = Stream.empty();
        while (iteratorFirst.hasNext() && iteratorSecond.hasNext()){
            resultStream = Stream.concat(resultStream, Stream.of(iteratorFirst.next(), iteratorSecond.next()));
        }
        return resultStream;
    }
}

person Serhii    schedule 16.07.2018    source источник
comment
Может быть, вы также включите то, что этот код должен делать, вместо того, чтобы предоставить читателю самому разобраться в этом.   -  person GhostCat    schedule 16.07.2018
comment
Вы чередуете два итератора?   -  person    schedule 16.07.2018
comment
Использование Java Stream API. Может быть, этот код нельзя заменить лямбда-выражением?   -  person Serhii    schedule 16.07.2018
comment
Просто метод, который чередует элементы из первого и второго потоков и останавливается, когда в одном из них заканчиваются элементы.   -  person Serhii    schedule 16.07.2018
comment
а, так вы собираетесь объединить два потока (a1,a2...) и (b1,b2...) и вернуть чередование (a1, b1, a2, b2...)? и, вероятно, вам нужна ленивая оценка следующих элементов, я прав?   -  person Patrick Parker    schedule 16.07.2018
comment
comment
@PatrickParker Это давно изменилось.   -  person    schedule 16.07.2018
comment
Что-то вроде Stream.generate(() -> null).takewhile(iteratorFirst.hasNext() && iteratorSecond.hasNext()).flatMap(ignored -> Stream.of(iteratorFirst.next(), iteratorSecond.next())) может подойти, но я не думаю, что это более читабельно, чем ваше существующее решение.   -  person Jaroslaw Pawlak    schedule 16.07.2018
comment
Или StreamSupport.stream(iteratorFirst.spliterator(), false).filter(element -> iteratorSecond.hasNext()).flatMap(element -> Stream.of(element, iteratorSecond.next())), но это снова нарушает контракт, так как Predicate должен быть без гражданства.   -  person Jaroslaw Pawlak    schedule 16.07.2018
comment
Я должен использовать только Java8, поэтому метод takeWhile для меня недействителен. Как я могу заменить его на Java8?   -  person Serhii    schedule 17.07.2018
comment
@Сергей Какой именно результат вам нужен?   -  person Pankaj Singhal    schedule 17.07.2018
comment
Например, поток первый [A, B, C, D], второй поток [1, 2, 3], выходной поток [A, 1, B, 2, C, 3].   -  person Serhii    schedule 17.07.2018
comment
@Сергей, на ваш вопрос ответили успешно?   -  person Patrick Parker    schedule 28.07.2018


Ответы (1)


Используя Guava's Streams.zip, вы можете объединить два потока в поток из двухэлементных потоков, который затем можно просто сгладить, чтобы получить чередующуюся последовательность:

return Streams.zip(first, second, (arg1, arg2) -> Stream.of(arg1, arg2))
    .flatMap(Function.identity());

Одно предостережение заключается в том, что результирующий поток не может быть эффективно разделен (см. связанный документ). Это может повредить параллельной производительности.

Примечание.

Если у вас нет доступа к Guava, вы можете реализовать свой собственный zip(a, b, bifunc), как показано здесь.

person Patrick Parker    schedule 17.07.2018