Stream utilities for Java 8
Branch: master
Clone or download
Dominic Fox
Dominic Fox Cycle
Latest commit 00c55a0 Mar 9, 2018
Type Name Latest commit message Commit time
Failed to load latest commit information.
src Cycle Mar 9, 2018
.gitignore Add IntelliJ IDEA files to .gitignore Mar 11, 2015
.travis.yml Travis picking Sep 2, 2014
LICENSE Initial commit Aug 18, 2014 Update Mar 17, 2017
pom.xml [maven-release-plugin] prepare for next development iteration Nov 21, 2017


Maven Central Build Status

A small collection of Stream utilities for Java 8. Protonpack provides the following:

  • takeWhile and takeUntil
  • skipWhile and skipUntil
  • zip and zipWithIndex
  • unfold
  • MapStream
  • aggregate
  • Streamable<T>
  • unique collector

For full API documentation, see (

Available from Maven Central:



Takes elements from the stream while the supplied condition is met. takeUntil does the same, but with the condition negated.

Stream<Integer> infiniteInts = Stream.iterate(0, i -> i + 1);
Stream<Integer> finiteInts = StreamUtils.takeWhile(infiniteInts, i -> i < 10);



Skips elements from the stream while the supplied condition is met. skipUntil does the same, but with the condition negated.

Stream<Integer> ints = Stream.of(1,2,3,4,5,6,7,8,9,10);
Stream<Integer> skipped = StreamUtils.skipWhile(ints, i -> i < 4);

List<Integer> collected = skipped.collect(Collectors.toList());

           contains(4, 5, 6, 7, 8, 9, 10));


Combines two streams using the supplied combiner function.

Stream<String> streamA = Stream.of("A", "B", "C");
Stream<String> streamB  = Stream.of("Apple", "Banana", "Carrot", "Doughnut");

List<String> zipped =,
                                      (a, b) -> a + " is for " + b)

           contains("A is for Apple", "B is for Banana", "C is for Carrot"));


Generates a (potentially infinite) stream using a generator that can indicate the end of the stream at any time by returning Optional.empty().

Stream<Integer> unfolded = StreamUtils.unfold(1, i ->
    (i < 10)
        ? Optional.of(i + 1)
        : Optional.empty());

           contains(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));


Transforms a source type into a stream

stream(Optional<T> optional):

Stream<Item> items = idStream.flatMap(id ->;


Streamable is to Stream as Iterable is to Iterator. Useful when you will want to stream repeatedly over some source.


A collector that returns the one and only item in a stream, if present, or throws an exception if multiple items are found.

assertThat(Stream.of(1, 2, 3).filter(i -> i > 3).collect(CollectorUtils.unique()),

assertThat(Stream.of(1, 2, 3).filter(i -> i > 2).collect(CollectorUtils.unique()),

// Throws NonUniqueValueException
Stream.of(1, 2, 3).filter(i -> i > 1).collect(CollectorUtils.unique());


A collector that converts a stream of CompletableFuture<T> into a CompletableFuture<List<T>>, which completes exceptionally if (and as soon as) any of the futures in the list completes exceptionally.

Function<Integer, CompletableFuture<Integer>> processAsynchronously = i -> CompletableFuture.completedFuture(i * 2);
        Stream.of(1, 2, 3).map(processAsynchronously)
        contains(2, 4, 6));