Подтвердить что ты не робот

Итерации двух Java-8-потоков вместе

Я хотел бы повторить два Java-8-Stream вместе, так что у меня есть на каждом итерационном шаге два аргумента. Что-то вроде этого, где somefunction создает нечто вроде Stream<Pair<A,B>>.

Stream<A> as;
Stream<B> bs;
somefunction (as, bs)
  .forEach ((a, b) -> foo (a, b));
// or something like
somefunction (as, bs)
  .forEach ((Pair<A, B> abs) -> foo (abs.left (), abs.right ()));

Я хочу знать, если Java предоставляет что-то подобное, хотя в Java нет Pair:-( Если нет такой API-функции, есть ли другой способ одновременного итерации двух потоков?

4b9b3361

Ответ 1

static <A, B> Stream<Pair<A, B>> zip(Stream<A> as, Stream<B> bs)
{
    Iterator<A> i=as.iterator();
    return bs.filter(x->i.hasNext()).map(b->new Pair<>(i.next(), b));
}

Это не обеспечивает параллельное выполнение, но и оригинальная реализация zip.

И как F. Böller отметил, что он не работает, если bs бесконечен, а as - нет. Для решения, которое работает для всех возможных комбинаций бесконечных и конечных потоков, промежуточный Iterator, который проверяет оба источника в методе hasNext, кажется неизбежным¹:

static <A, B> Stream<Pair<A,B>> zip(Stream<A> as, Stream<B> bs) {
    Iterator<A> i1 = as.iterator();
    Iterator<B> i2 = bs.iterator();
    Iterable<Pair<A,B>> i=()->new Iterator<Pair<A,B>>() {
        public boolean hasNext() {
            return i1.hasNext() && i2.hasNext();
        }
        public Pair<A,B> next() {
            return new Pair<A,B>(i1.next(), i2.next());
        }
    };
    return StreamSupport.stream(i.spliterator(), false);
}

Если вы хотите использовать возможность параллельной записи, вам следует рассмотреть источник Stream. Например. вы можете закрепить два ArrayList (или любой RandomAccessList), например

ArrayList<Foo> l1=new ArrayList<>();
ArrayList<Bar> l2=new ArrayList<>();
IntStream.range(0, Math.min(l1.size(), l2.size()))
         .mapToObj(i->new Pair(l1.get(i), l2.get(i)))
         . …

¹ (если вы не реализуете непосредственно Spliterator)

Ответ 2

AFAIK не похож на ваше требование, но то, что вы можете сделать, это создать два потока и передать потоки этим потокам. Каждый поток будет итерировать потоки и применять к нему некоторую логику. Создание темы стало легко с помощью java 8.

new Thread(
    () -> System.out.println("hello world")
).start();