summaryrefslogtreecommitdiff
path: root/src/main/java/au/id/zancanaro/javacheck/Iterators.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/au/id/zancanaro/javacheck/Iterators.java')
-rw-r--r--src/main/java/au/id/zancanaro/javacheck/Iterators.java177
1 files changed, 177 insertions, 0 deletions
diff --git a/src/main/java/au/id/zancanaro/javacheck/Iterators.java b/src/main/java/au/id/zancanaro/javacheck/Iterators.java
new file mode 100644
index 0000000..347a927
--- /dev/null
+++ b/src/main/java/au/id/zancanaro/javacheck/Iterators.java
@@ -0,0 +1,177 @@
+package au.id.zancanaro.javacheck;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+public final class Iterators {
+ private Iterators() {
+ }
+
+ public static <T> RangeIterator<T> rangeIterator(int countTo, Function<Integer,T> fn) {
+ return new RangeIterator<T>(countTo, fn);
+ }
+
+ private static class RangeIterator<T> implements Iterator<T> {
+ private final Function<Integer, T> action;
+ private final int countTo;
+ private int index = 0;
+
+ public RangeIterator(int countTo, Function<Integer, T> action) {
+ this.countTo = countTo;
+ this.action = action;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return index < countTo;
+ }
+
+ @Override
+ public T next() {
+ return action.apply(index++);
+ }
+ }
+
+ public static <T> FlattenIterator<T> flatten(Iterator<Iterator<T>> iterators) {
+ return new FlattenIterator<>(iterators);
+ }
+ public static class FlattenIterator<T> implements Iterator<T> {
+ private Iterator<T> current;
+
+ private Iterator<Iterator<T>> iterators;
+
+ public FlattenIterator(Iterator<Iterator<T>> iterators) {
+ this.current = Iterators.emptyIterator();
+ this.iterators = iterators;
+ }
+
+ private Iterator<T> getCurrent() {
+ while (!current.hasNext() && iterators.hasNext()) {
+ current = iterators.next();
+ }
+ return current;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return getCurrent().hasNext();
+ }
+ @Override
+ public T next() {
+ return getCurrent().next();
+ }
+
+ }
+
+ public static <T> ConcatIterator<T> concat(Iterator<T> left, Iterator<T> right) {
+ return new ConcatIterator<>(left, right);
+ }
+ public static class ConcatIterator<T> implements Iterator<T> {
+ private final Iterator<T> left;
+
+ private final Iterator<T> right;
+
+ public ConcatIterator(Iterator<T> left, Iterator<T> right) {
+ this.left = left;
+ this.right = right;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return left.hasNext() || right.hasNext();
+ }
+ @Override
+ public T next() {
+ if (left.hasNext()) {
+ return left.next();
+ } else {
+ return right.next();
+ }
+ }
+
+ }
+
+ public static <T> EmptyIterator<T> emptyIterator() {
+ return new EmptyIterator<>();
+ }
+ public static class EmptyIterator<T> implements Iterator<T> {
+
+ @Override
+ public boolean hasNext() {
+ return false;
+ }
+ @Override
+ public T next() {
+ return null;
+ }
+
+ }
+
+ public static <T,R> MappingIterator<T,R> mappingIterator(Function<T,R> f, Iterator<T> iterator) {
+ return new MappingIterator<>(f, iterator);
+ }
+ private static class MappingIterator<T, R> implements Iterator<R> {
+ private final Function<T, R> mapping;
+
+ private final Iterator<T> iterator;
+
+ public MappingIterator(Function<T, R> mapping, Iterator<T> iterator) {
+ this.mapping = mapping;
+ this.iterator = iterator;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return iterator.hasNext();
+ }
+ @Override
+ public R next() {
+ return mapping.apply(iterator.next());
+ }
+
+ }
+
+ public static <T> FilteringIterator<T> filteringIterator(Predicate<T> pred, Iterator<T> iterator) {
+ return new FilteringIterator<>(pred, iterator);
+ }
+
+ private static class FilteringIterator<T> implements Iterator<T> {
+ private final Predicate<T> predicate;
+ private final Iterator<T> iterator;
+ private List<T> nextValue;
+
+ public FilteringIterator(Predicate<T> pred, Iterator<T> iterator) {
+ this.predicate = pred;
+ this.iterator = iterator;
+ this.nextValue = null;
+ }
+
+ private void populateNext() {
+ while (nextValue == null && iterator.hasNext()) {
+ T value = iterator.next();
+ if (predicate.test(value)) {
+ nextValue = Collections.singletonList(value);
+ } else {
+ nextValue = null;
+ }
+ }
+ }
+
+ @Override
+ public boolean hasNext() {
+ populateNext();
+ return nextValue != null;
+ }
+
+ @Override
+ public T next() {
+ populateNext();
+ T result = nextValue.get(0);
+ nextValue = null;
+ return result;
+ }
+ }
+}