Can you split a stream into two streams?

前端 未结 10 656
栀梦
栀梦 2020-11-27 12:03

I have a data set represented by a Java 8 stream:

Stream stream = ...;

I can see how to filter it to get a random subset - for exa

相关标签:
10条回答
  • 2020-11-27 12:35

    Not exactly. You can't get two Streams out of one; this doesn't make sense -- how would you iterate over one without needing to generate the other at the same time? A stream can only be operated over once.

    However, if you want to dump them into a list or something, you could do

    stream.forEach((x) -> ((x == 0) ? heads : tails).add(x));
    
    0 讨论(0)
  • 2020-11-27 12:39

    How about:

    Supplier<Stream<Integer>> randomIntsStreamSupplier =
        () -> (new Random()).ints(0, 2).boxed();
    
    Stream<Integer> tails =
        randomIntsStreamSupplier.get().filter(x->x.equals(0));
    Stream<Integer> heads =
        randomIntsStreamSupplier.get().filter(x->x.equals(1));
    
    0 讨论(0)
  • 2020-11-27 12:43

    I stumbled across this question to my self and I feel that a forked stream has some use cases that could prove valid. I wrote the code below as a consumer so that it does not do anything but you could apply it to functions and anything else you might come across.

    class PredicateSplitterConsumer<T> implements Consumer<T>
    {
      private Predicate<T> predicate;
      private Consumer<T>  positiveConsumer;
      private Consumer<T>  negativeConsumer;
    
      public PredicateSplitterConsumer(Predicate<T> predicate, Consumer<T> positive, Consumer<T> negative)
      {
        this.predicate = predicate;
        this.positiveConsumer = positive;
        this.negativeConsumer = negative;
      }
    
      @Override
      public void accept(T t)
      {
        if (predicate.test(t))
        {
          positiveConsumer.accept(t);
        }
        else
        {
          negativeConsumer.accept(t);
        }
      }
    }
    

    Now your code implementation could be something like this:

    personsArray.forEach(
            new PredicateSplitterConsumer<>(
                person -> person.getDateOfBirth().isPresent(),
                person -> System.out.println(person.getName()),
                person -> System.out.println(person.getName() + " does not have Date of birth")));
    
    0 讨论(0)
  • 2020-11-27 12:49

    This is against the general mechanism of Stream. Say you can split Stream S0 to Sa and Sb like you wanted. Performing any terminal operation, say count(), on Sa will necessarily "consume" all elements in S0. Therefore Sb lost its data source.

    Previously, Stream had a tee() method, I think, which duplicate a stream to two. It's removed now.

    Stream has a peek() method though, you might be able to use it to achieve your requirements.

    0 讨论(0)
提交回复
热议问题