diff options
Diffstat (limited to 'src/main/java/au/id/zancanaro/javacheck/Iterators.java')
-rw-r--r-- | src/main/java/au/id/zancanaro/javacheck/Iterators.java | 177 |
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; + } + } +} |