From b435b8659eef0e8bc2910966d87b5b74b4cddbe2 Mon Sep 17 00:00:00 2001 From: Carlo Zancanaro Date: Thu, 4 Jun 2015 16:46:31 +1000 Subject: Move stuff over to using streams instead of iterators: much nicer! --- .../java/au/id/zancanaro/javacheck/ShrinkTree.java | 101 ++++++++++----------- 1 file changed, 49 insertions(+), 52 deletions(-) (limited to 'src/main/java/au/id/zancanaro/javacheck/ShrinkTree.java') diff --git a/src/main/java/au/id/zancanaro/javacheck/ShrinkTree.java b/src/main/java/au/id/zancanaro/javacheck/ShrinkTree.java index bdc7604..4337c14 100644 --- a/src/main/java/au/id/zancanaro/javacheck/ShrinkTree.java +++ b/src/main/java/au/id/zancanaro/javacheck/ShrinkTree.java @@ -3,20 +3,20 @@ package au.id.zancanaro.javacheck; import java.io.IOException; import java.io.Writer; import java.util.ArrayList; -import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.function.Function; import java.util.function.Predicate; - -import static au.id.zancanaro.javacheck.Iterators.*; +import java.util.function.Supplier; +import java.util.stream.IntStream; +import java.util.stream.Stream; @SuppressWarnings("unused") public class ShrinkTree { private final T value; - private final Iterable> children; + private final Supplier>> children; - private ShrinkTree(T value, Iterable> children) { + private ShrinkTree(T value, Supplier>> children) { this.value = value; this.children = children; } @@ -25,20 +25,23 @@ public class ShrinkTree { return value; } - public Iterator> getChildren() { - return children.iterator(); + public Stream> getChildren() { + return children.get(); } + @SuppressWarnings("Convert2MethodRef") public static ShrinkTree pure(T value) { - return new ShrinkTree<>(value, Collections.emptyList()); + // Converting the () -> Stream.empty() into Stream::empty actually + // breaks Java's generic type inference. Who would have thought? + return new ShrinkTree<>(value, () -> Stream.empty()); } public static ShrinkTree join(ShrinkTree> tree) { return new ShrinkTree<>( tree.getValue().getValue(), - () -> concat( - mappingIterator(ShrinkTree::join, tree.children.iterator()), - tree.getValue().children.iterator())); + () -> Stream.concat( + tree.getChildren().map(ShrinkTree::join), + tree.getValue().getChildren())); } private static List makeHeadList(ShrinkTree[] trees) { @@ -49,48 +52,42 @@ public class ShrinkTree { return heads; } - public static Iterator[]> promoteChildren(ShrinkTree[] trees) { - return flatten( - rangeIterator(trees.length, index -> - mappingIterator(child -> { - @SuppressWarnings("unchecked") - ShrinkTree[] result = (ShrinkTree[]) new ShrinkTree[trees.length]; - for (int i = 0; i < trees.length; ++i) { - result[i] = (i == index ? child : trees[i]); - } - return result; - }, trees[index].getChildren()))); - } - - public static Iterator[]> removeChildren(ShrinkTree[] trees) { - return rangeIterator(trees.length, index -> { - @SuppressWarnings("unchecked") - ShrinkTree[] result = (ShrinkTree[]) new ShrinkTree[trees.length - 1]; - for (int i = 0; i < trees.length - 1; ++i) { - result[i] = trees[(i >= index ? i + 1 : i)]; - } - return result; - }); + @SuppressWarnings("unchecked") + public static Stream[]> promoteChildren(ShrinkTree[] trees) { + return IntStream.range(0, trees.length) + .mapToObj(index -> trees[index].getChildren().map(child -> + IntStream.range(0, trees.length) + .mapToObj(i -> (i == index ? child : trees[i])) + .toArray(ShrinkTree[]::new))) + .flatMap(x -> x) + .map(x -> (ShrinkTree[]) x); } - public static Iterator[]> removeAndPromoteChildren(ShrinkTree[] trees) { - return concat(removeChildren(trees), promoteChildren(trees)); + public static Stream[]> removeChildren(ShrinkTree[] trees) { + return IntStream.range(0, trees.length) + .mapToObj(index -> IntStream.range(0, trees.length) + .filter(i -> i != index) + .mapToObj(i -> trees[i]) + .toArray(ShrinkTree[]::new)); + } + + public static Stream[]> removeAndPromoteChildren(ShrinkTree[] trees) { + return Stream.concat(removeChildren(trees), promoteChildren(trees)); } public static ShrinkTree> combine( ShrinkTree[] trees, - Function[], Iterator[]>> processChildren) { + Function[], Stream[]>> processChildren) { return new ShrinkTree<>( makeHeadList(trees), - () -> mappingIterator( - shrinks -> ShrinkTree.combine(shrinks, processChildren), - processChildren.apply(trees))); + () -> processChildren.apply(trees) + .map(shrinks -> combine(shrinks, processChildren))); } public ShrinkTree map(Function f) { return new ShrinkTree<>( f.apply(this.value), - () -> mappingIterator(tree -> tree.map(f), this.children.iterator())); + () -> this.getChildren().map(tree -> tree.map(f))); } public ShrinkTree flatMap(Function> f) { @@ -101,24 +98,20 @@ public class ShrinkTree { if (predicate.test(this.getValue())) { return new ShrinkTree<>( this.getValue(), - () -> mappingIterator(tree -> tree.filter(predicate), - filteringIterator( - tree -> predicate.test(tree.getValue()), - this.getChildren()))); + () -> this.getChildren() + .filter(tree -> predicate.test(tree.getValue())) + .map(tree -> tree.filter(predicate))); } else { throw new IllegalArgumentException("Current value doesn't match predicate: whoops!"); } } public ShrinkTree withShrinkStrategy(ShrinkStrategy strategy) { - return new ShrinkTree<>(this.getValue(), strategyIterable(this.getValue(), strategy)); + return new ShrinkTree<>(this.getValue(), () -> strategyStream(this.getValue(), strategy)); } - private static Iterable> strategyIterable(final T value, final ShrinkStrategy strategy) { - return () -> - mappingIterator( - v -> new ShrinkTree<>(v, strategyIterable(v, strategy)), - strategy.shrink(value)); + private static Stream> strategyStream(final T value, final ShrinkStrategy strategy) { + return strategy.shrink(value).map(v -> new ShrinkTree<>(v, () -> strategyStream(v, strategy))); } public void print(Writer output) throws IOException { @@ -128,8 +121,12 @@ public class ShrinkTree { public void print(Writer output, Function toString) throws IOException { output.write(toString.apply(this.getValue())); output.write('['); - for (ShrinkTree child : children) { - child.print(output, toString); + Iterator> iterator = children.get().iterator(); + while (iterator.hasNext()) { + iterator.next().print(output, toString); + if (iterator.hasNext()) { + output.write(' '); + } } output.write(']'); output.flush(); -- cgit v1.2.3