A Java library that provides PairedIterator and PairedIterable utilities for
iterating over two collections of different types simultaneously.
The standard Java Collections Framework and Apache Commons Collections lack
native support for "zipping" iterators of different types. While Apache Commons
Collections provides a ZippingIterator,
it only works with iterators of the same type.
There is a Streams.zip
in Google Guava library which works only with Streams and not with Iterators/Iterables, also lacks
an inbuilt Pair class.
This library addresses that limitation by introducing PairedIterator and
PairedIterable, which allow you to iterate over two collections with
different element types in tandem. This functionality is particularly useful
when:
- Working with parallel data structures (e.g., IDs and names)
- Processing related data from different sources
- Combining heterogeneous collections for transformation or analysis
This implementation is based on my original proposal COLLECTIONS-795 and PR#442
- Type-Safe Iteration: Full generic type support for left and right iterators
- Flexible Construction: Create from
IteratororIterablesources - Stream Support: Convert to Java streams via
PairedIterable - Early Termination: Automatically stops when either iterator is exhausted
- Immutable Results: Returns immutable
PairedItemtuples - Zero Dependencies: Requires Java 17+ and Apache Commons Collections 4.5+
- Java 17 or higher
- Apache Commons Collections 4.5.0+
Add source dependencies to your Gradle project
In settings.gradle:
sourceControl {
gitRepository("https://github.com/anantdamle/collections.git") {
producesModule("xyz.damle.collections:collections")
}
}In build.gradle:
dependencies {
implementation 'xyz.damle.collections:collections:0.0.1'
}import xyz.damle.collections.iterators.PairedIterator;
import xyz.damle.collections.iterators.PairedIterator.PairedItem;
List<Integer> studentIds = List.of(1001, 1002, 1003);
List<String> studentNames = List.of("Alice", "Bob", "Charlie");
PairedIterator<Integer, String> pairedIterator =
PairedIterator.ofIterables(studentIds, studentNames);
while (pairedIterator.hasNext()) {
PairedItem<Integer, String> item = pairedIterator.next();
System.out.println(
"ID: " + item.leftItem() + ", Name: " + item.rightItem());
}import xyz.damle.collections.PairedIterable;
import xyz.damle.collections.iterators.PairedIterator.PairedItem;
List<Integer> studentIds = List.of(1001, 1002, 1003);
List<String> studentNames = List.of("Alice", "Bob", "Charlie");
for (var item : PairedIterable.of(studentIds, studentNames)) {
System.out.println("ID: " + item.leftItem() + ", Name: " + item.rightItem());
}import xyz.damle.collections.PairedIterable;
List<Integer> studentIds = List.of(1001, 1002, 1003);
List<String> studentNames = List.of("Alice", "Bob", "Charlie");
PairedIterable.of(studentIds, studentNames)
.stream()
.filter(item -> item.leftItem() > 1001)
.forEach(item -> System.out.println(item.rightItem()));Iterator<Integer> idIterator = ...;
Iterator<String> nameIterator = ...;
PairedIterator<Integer, String> pairedIterator =
PairedIterator.of(idIterator, nameIterator);PairedIterator.of(Iterator<L> left, Iterator<R> right)- Create from two iteratorsPairedIterator.ofIterables(Iterable<L> left, Iterable<R> right)- Create from two iterableshasNext()- Returns true if both iterators have remaining elementsnext()- Returns nextPairedItem<L, R>containing elements from both iterators
PairedIterable.of(Iterable<L> left, Iterable<R> right)- Create paired iterableiterator()- Returns aPairedIteratorstream()- Returns aStream<PairedItem<L, R>>
leftItem()- Get the left elementrightItem()- Get the right elementtoString()- Returns string representation:{leftItem, rightItem}
- Early Termination: Iteration stops when either iterator is exhausted
- Null Safety: Constructor parameters are null-checked
- Immutability:
PairedItemis implemented as a Java record and is immutable - No Remove Support: The
remove()operation is not supported
./gradlew build./gradlew test./gradlew jacocoTestReportLicensed under the Apache License, Version 2.0. See LICENSE for details.
This library is based on a contribution to Apache Commons Collections. For issues or improvements, please open an issue on the repository.
Anant Damle