v4.0.0 — Virtual Threads

Parallel
Collectors

Custom java.util.stream.Collector implementations for parallel processing with CompletableFutures and Virtual Threads. Zero dependencies.

implementation 'com.pivovarit:parallel-collectors:4.0.0' click to copy

Built for real-world
parallel workloads

Standard parallel streams use the shared ForkJoinPool — terrible for I/O-bound work. Parallel Collectors fix that.

Virtual Threads

Defaults to Virtual Threads on JDK 21+. Lightweight concurrency without managing thread pools.

Non-blocking

Returns CompletableFuture — the calling thread never blocks. Compose, chain, and add timeouts freely.

Configurable

Custom executors, parallelism limits, and batching. Full control over how work gets distributed.

Batching

Group fine-grained tasks into batches to minimize contention. Benchmarked up to 162x speedup.

Zero dependencies

Nothing but the JDK. No transitive dependency trees, no version conflicts, no bloat.

Short-circuiting

If one operation throws, remaining tasks are cancelled and in-flight tasks are interrupted where possible.

Parallel streams,
done right

Familiar Stream API patterns with parallel execution backed by CompletableFuture.

// Parallel collection with Virtual Threads (default)
CompletableFuture<List<String>> result = urls.stream()
  .collect(parallel(url -> fetchData(url), toList()));
// With parallelism limit, batching, custom executor
CompletableFuture<List<String>> result = urls.stream()
  .collect(parallel(url -> fetchData(url), c -> c
    .parallelism(64)
    .batching()
  , toList()));
// Stream results as they complete
Stream<String> result = urls.stream()
  .collect(parallelToStream(url -> fetchData(url)));

// Or preserve input order
Stream<String> ordered = urls.stream()
  .collect(parallelToStream(url -> fetchData(url), c -> c.ordered()));
// Non-blocking with timeout and async callback
urls.stream()
  .collect(parallel(url -> fetchData(url), toList()))
  .orTimeout(5, SECONDS)
  .thenAccept(System.out::println);

Core collectors

Static factory methods on ParallelCollectors — follows java.util.stream.Collectors conventions.

parallel(mapper, collector) CompletableFuture<R>

Parallel mapping with a downstream collector for reduction. Returns a future of the collected result.

parallel(mapper) CompletableFuture<Stream<R>>

Parallel mapping without reduction. Returns a future wrapping a stream of mapped results.

parallelToStream(mapper) Stream<R>

Returns a stream that emits results in completion order. Use c → c.ordered() to preserve input order.

parallelToStreamBy(classifier, mapper) Stream<Group<K, R>>

Classifies elements into groups and streams grouped results as they complete.

parallelBy(classifier, mapper) CompletableFuture<Stream<Group>>

Classifies elements into groups and processes each group in parallel. Results keyed by group.

parallelBy(classifier, mapper, collector) CompletableFuture<R>

Groups elements in parallel and reduces grouped results with a downstream collector.

// The Configurer API — fluent configuration for all collectors
urls.stream().collect(parallel(url -> fetch(url), c -> c
    .executor(myExecutor)       // custom Executor (default: Virtual Threads)
    .parallelism(32)           // max concurrent tasks
    .batching()                // group work into batches
, toList()));

// Streaming collectors also support ordered emission
urls.stream().collect(parallelToStream(url -> fetch(url), c -> c
    .ordered()                 // preserve input order
    .parallelism(32)
));

Add to your project

Maven

JDK 21+
<dependency>
  <groupId>com.pivovarit</groupId>
  <artifactId>parallel-collectors</artifactId>
  <version>4.0.0</version>
</dependency>

Gradle

JDK 21+
implementation 'com.pivovarit:parallel-collectors:4.0.0'

Maven

JDK 8+
<dependency>
  <groupId>com.pivovarit</groupId>
  <artifactId>parallel-collectors</artifactId>
  <version>2.6.1</version>
</dependency>

Gradle

JDK 8+
implementation 'com.pivovarit:parallel-collectors:2.6.1'
JDK 21+ recommended — version 3.x uses Virtual Threads by default. Version 2.x supports JDK 8+ with platform threads.