Как реализовать универсальный метод Java 8, который возвращает сжатый поток, в котором объекты из двух потоков появляются по очереди? - PullRequest
2 голосов
/ 13 марта 2019

Я попытался реализовать универсальный метод, который возвращает сжатый поток из двух потоков. Возвращаемый поток должен быть объединением двух потоков, в которых элементы появляются по очереди, и основываться на двух потоках, которые передаются этому методу. Если один поток длиннее другого, он должен содержать значения из более длинного потока в конце. Код, который я придумал:

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Stream;

public class Task12 {

public static void main(String[] args) {

    Stream<Integer> stream1 = Stream.iterate(0, integer -> integer)
            .limit(20);

    Stream<Integer> stream2 = Stream.iterate(1, integer -> integer)
            .limit(20);

    Stream<Integer> zippedStreams = zip(stream1, stream2);

    zippedStreams.forEach(System.out::println);

}

private static <T> Stream<T> zip(Stream<T> first, Stream<T> second) {

    Iterator<T> iterator1 = first.iterator();
    Iterator<T> iterator2 = second.iterator();

    List<T> elements = new LinkedList<>();


    while (iterator1.hasNext() || iterator2.hasNext()) {
        if (iterator1.hasNext()) {
            elements.add(iterator1.next());
        }

        if(iterator2.hasNext()) {
            elements.add(iterator2.next());
        }
    }

    return elements.stream();

}

У меня есть несколько вопросов об этой реализации:

  1. есть ли лучший способ реализовать это?
  2. что если один из потоков будет бесконечным потоком? Есть ли способ ограничить возвращаемый поток точным количеством элементов - кроме использования метода «limit» и передачи лимита в качестве параметра для метода «zip»?

1 Ответ

3 голосов
/ 15 марта 2019

Есть способ построить поток из итератора / итерируемого.Это очень близко к вашему решению, но таким образом, оно обрабатывает бесконечный поток также

public static void main(String[] args) {

        Stream<Integer> stream1 = Stream.iterate(0, integer -> integer);

        Stream<Integer> stream2 = Stream.iterate(1, integer -> integer)
                .limit(4);

        Stream<Integer> zippedStreams = StreamSupport.stream(new Ziperator<>(stream1, stream2).spliterator(), false);

        zippedStreams.limit(15).forEach(System.out::println);

    }


    public static class Ziperator<T> implements Iterator<T>, Iterable<T>{
        Iterator<T> iterator1;
        Iterator<T> iterator2;
        boolean even = true;


        @Override
        public Iterator<T> iterator() {
            return this;
        }

        public Ziperator(Stream<T> first, Stream<T> second) {
            iterator1 = first.iterator();
            iterator2 = second.iterator();
        }

        public boolean hasNext(){
            return iterator1.hasNext() || iterator2.hasNext();
        }

        @Override
        public T next() {
            if(!iterator2.hasNext()){
                even = true;
            }
            if(!iterator1.hasNext()){
                even = false;
            }
            if (even) {
                even = false;
                return iterator1.next();
            } else {
                even = true;
                return iterator2.next();
            }
        }

        @Override
        public void remove() {

        }
    }

Выход для этого

0
1
0
1
0
1
0
1
0
0
0
0
0
0
0

Этот код может быть очищен / оптимизирован, но это работаетбаза:)

...