How can one find an item after the match using streams?

I found it through this blog post:
http://blog.jooq.org/2014/09/10/when-the-java-8-streams-api-is-not-enough/

The library called jOOL has a Github link
https://github.com/jOOQ/jOOL

and Maven central Info here:
http://mvnrepository.com/artifact/org.jooq/jool/0.9.6

The code for the example became:

import org.jooq.lambda.Seq;

...

    String result = Seq.of(args)
            .skipWhile(s -> !s.matches("-b.*"))
            .skip(1)
            .findFirst()
            .get();

This is the kind of spliterator it takes to have this solved with streams:

import java.util.ArrayList;
import java.util.List;
import java.util.Spliterator;
import java.util.Spliterators.AbstractSpliterator;
import java.util.function.Consumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

public class PartitioningSpliterator<E> extends AbstractSpliterator<List<E>>
{
  private final Spliterator<E> spliterator;
  private final int partitionSize;

  public PartitioningSpliterator(Spliterator<E> toWrap, int partitionSize) {
    super(toWrap.estimateSize(), toWrap.characteristics());
    if (partitionSize <= 0) throw new IllegalArgumentException(
        "Partition size must be positive, but was " + partitionSize);
    this.spliterator = toWrap;
    this.partitionSize = partitionSize;
  }

  public static <E> Stream<List<E>> partition(Stream<E> in, int size) {
    return StreamSupport.stream(new PartitioningSpliterator(in.spliterator(), size), false);
  }

  @Override public boolean tryAdvance(Consumer<? super List<E>> action) {
    final HoldingConsumer<E> holder = new HoldingConsumer<>();
    if (!spliterator.tryAdvance(holder)) return false;
    final ArrayList<E> partition = new ArrayList<>(partitionSize);
    int j = 0;
    do partition.add(holder.value); while (++j < partitionSize && spliterator.tryAdvance(holder));
    action.accept(partition);
    return true;
  }

  @Override public long estimateSize() {
    final long est = spliterator.estimateSize();
    return est == Long.MAX_VALUE? est
         : est / partitionSize + (est % partitionSize > 0? 1 : 0);
  }

  static final class HoldingConsumer<T> implements Consumer<T> {
    T value;
    @Override public void accept(T value) { this.value = value; }
  }
}

Once you have this tucked away somewhere in the project, you can say

partition(Stream.of("-a","1","-b","2","-c","3"), 2)
      .filter(pair -> pair.get(0).equals("-b"))
      .findFirst()
      .map(pair -> pair.get(1))
      .orElse("");

As a side point, the presented spliterator supports parallelism by relying on the default implementation of trySplit in AbstractSpliterator.

Tags:

Java

Lambda

Regex