在Java 8中给出谓词的两个流元素之间进行选择

时间:2017-03-07 18:20:30

标签: java-8 java-stream

我有两个Java Stream<String> AB

如果给出谓词p,我在每一步中如何从AB中选择一个元素?未被挑选的元素必须保留在流的头部,以便下次尝试时可以选择它。

2 个答案:

答案 0 :(得分:1)

使用可以使用zip方法。标准库不包含标准库,但您可以复制下面显示的源代码(来自this question)。

import java.util.Arrays;
import java.util.List;
import java.util.function.BiFunction;
import java.util.stream.Collectors;


class Main {
    public static void main(String[] args) {
        List<String> list1 = Arrays.asList("a1", "a2", "a3");
        List<String> list2 = Arrays.asList("b1", "b2", "b3");

        BiFunction<String, String, String> picker = (a, b) -> {
            // pick whether you want a from list1, or b from list2
            return a;
        };

        List<String> result = 
            StreamUtils.zip(list1.stream(), list2.stream(), picker)
            .collect(Collectors.toList());

        System.out.println(result);
    }
}

StreamUtils.java

import java.util.Objects;
import java.util.Iterator;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import java.util.function.BiFunction;

public class StreamUtils {
    public static<A, B, C> Stream<C> zip(Stream<? extends A> a,
                                         Stream<? extends B> b,
                                         BiFunction<? super A, ? super B, ? extends C> zipper) {
        Objects.requireNonNull(zipper);
        Spliterator<? extends A> aSpliterator = Objects.requireNonNull(a).spliterator();
        Spliterator<? extends B> bSpliterator = Objects.requireNonNull(b).spliterator();

        // Zipping looses DISTINCT and SORTED characteristics
        int characteristics = aSpliterator.characteristics() & bSpliterator.characteristics() &
                ~(Spliterator.DISTINCT | Spliterator.SORTED);

        long zipSize = ((characteristics & Spliterator.SIZED) != 0)
                ? Math.min(aSpliterator.getExactSizeIfKnown(), bSpliterator.getExactSizeIfKnown())
                : -1;

        Iterator<A> aIterator = Spliterators.iterator(aSpliterator);
        Iterator<B> bIterator = Spliterators.iterator(bSpliterator);
        Iterator<C> cIterator = new Iterator<C>() {
            @Override
            public boolean hasNext() {
                return aIterator.hasNext() && bIterator.hasNext();
            }

            @Override
            public C next() {
                return zipper.apply(aIterator.next(), bIterator.next());
            }
        };

        Spliterator<C> split = Spliterators.spliterator(cIterator, zipSize, characteristics);
        return (a.isParallel() || b.isParallel())
               ? StreamSupport.stream(split, true)
               : StreamSupport.stream(split, false);
    }
}

答案 1 :(得分:0)

如果两个输入流已经通过合并函数排序,则最终将通过合并函数对新流进行排序。它会像合并排序一样。所以你只需要连接两个流,然后排序。

final Stream<String> a = Stream.of("a", "b", "c");
final Stream<String> b = Stream.of("1", "2", "3");        
Stream.concat(a, b).sorted((a, b) -> mergeFunction /* TODO */);

否则,您可能需要AbacusUtil中的流API:

final Stream<String> a = Stream.of("a", "b", "c");
final Stream<String> b = Stream.of("1", "2", "3");        
Stream.merge(a, b, mergeFunction);