From 64e6564dce717b51c0a6330b710988ffb70c789a Mon Sep 17 00:00:00 2001 From: Michael-Georg Date: Fri, 14 Apr 2017 17:29:58 +0300 Subject: [PATCH 1/2] RectangleSpliterator & ZipWithIndexDoubleSpliterator + Tests --- .../part1/exercise/RectangleSpliterator.java | 32 +++++++++--- .../ZipWithIndexDoubleSpliterator.java | 26 +++++----- .../exercise/RectangleSpliteratorTest.java | 42 ++++++++++++++++ .../ZipWithIndexDoubleSpliteratorTest.java | 49 +++++++++++++++++++ 4 files changed, 127 insertions(+), 22 deletions(-) create mode 100644 src/test/java/spliterators/part1/exercise/RectangleSpliteratorTest.java create mode 100644 src/test/java/spliterators/part2/exercise/ZipWithIndexDoubleSpliteratorTest.java diff --git a/src/main/java/spliterators/part1/exercise/RectangleSpliterator.java b/src/main/java/spliterators/part1/exercise/RectangleSpliterator.java index 678f4f5..dc4f035 100755 --- a/src/main/java/spliterators/part1/exercise/RectangleSpliterator.java +++ b/src/main/java/spliterators/part1/exercise/RectangleSpliterator.java @@ -9,9 +9,9 @@ public class RectangleSpliterator extends Spliterators.AbstractIntSpliterator { private final int innerLength; private final int[][] array; - private final int startOuterInclusive; + private int startOuterInclusive; private final int endOuterExclusive; - private final int startInnerInclusive; + private int startInnerInclusive; public RectangleSpliterator(int[][] array) { this(array, 0, array.length, 0); @@ -29,18 +29,36 @@ private RectangleSpliterator(int[][] array, int startOuterInclusive, int endOute @Override public OfInt trySplit() { - // TODO - throw new UnsupportedOperationException(); + int length = endOuterExclusive - startOuterInclusive; + if (length <= 1) + return null; + + int middle = startOuterInclusive + length / 2; + RectangleSpliterator spliterator = new RectangleSpliterator(array, startOuterInclusive, + middle, 0); + startOuterInclusive = middle; + return spliterator; } @Override public long estimateSize() { - return ((long) endOuterExclusive - startOuterInclusive)*innerLength - startInnerInclusive; + return ((long) endOuterExclusive - startOuterInclusive) * innerLength - startInnerInclusive; } @Override public boolean tryAdvance(IntConsumer action) { - // TODO - throw new UnsupportedOperationException(); + if (startInnerInclusive < array[startOuterInclusive].length) { + action.accept(array[startOuterInclusive][startInnerInclusive]); + startInnerInclusive ++; + return true; + } else if (startOuterInclusive < endOuterExclusive-1) { + startInnerInclusive = 0; + ++startOuterInclusive; + action.accept(array[startOuterInclusive][startInnerInclusive]); + startInnerInclusive++; + return true; + } else + return false; } } + diff --git a/src/main/java/spliterators/part2/exercise/ZipWithIndexDoubleSpliterator.java b/src/main/java/spliterators/part2/exercise/ZipWithIndexDoubleSpliterator.java index deb4867..cb934a2 100755 --- a/src/main/java/spliterators/part2/exercise/ZipWithIndexDoubleSpliterator.java +++ b/src/main/java/spliterators/part2/exercise/ZipWithIndexDoubleSpliterator.java @@ -3,6 +3,7 @@ import java.util.Spliterator; import java.util.Spliterators; import java.util.function.Consumer; +import java.util.function.DoubleConsumer; public class ZipWithIndexDoubleSpliterator extends Spliterators.AbstractSpliterator { @@ -14,7 +15,7 @@ public ZipWithIndexDoubleSpliterator(OfDouble inner) { this(0, inner); } - private ZipWithIndexDoubleSpliterator(int firstIndex, OfDouble inner) { + public ZipWithIndexDoubleSpliterator(int firstIndex, OfDouble inner) { super(inner.estimateSize(), inner.characteristics()); currentIndex = firstIndex; this.inner = inner; @@ -22,35 +23,30 @@ private ZipWithIndexDoubleSpliterator(int firstIndex, OfDouble inner) { @Override public int characteristics() { - // TODO - throw new UnsupportedOperationException(); + return inner.characteristics(); } @Override public boolean tryAdvance(Consumer action) { - // TODO - throw new UnsupportedOperationException(); + DoubleConsumer doubleConsumer = (t) -> action.accept(new IndexedDoublePair(currentIndex++, t)); + return inner.tryAdvance(doubleConsumer); } @Override public void forEachRemaining(Consumer action) { - // TODO - throw new UnsupportedOperationException(); + inner.forEachRemaining((Double a) -> action.accept(new IndexedDoublePair(currentIndex++, a))); } @Override public Spliterator trySplit() { - // TODO - // if (inner.hasCharacteristics(???)) { - // use inner.trySplit - // } else - - return super.trySplit(); + if (inner.hasCharacteristics(SUBSIZED)) { + return new ZipWithIndexDoubleSpliterator(currentIndex++, inner.trySplit()); + } else + return super.trySplit(); } @Override public long estimateSize() { - // TODO - throw new UnsupportedOperationException(); + return currentIndex; } } diff --git a/src/test/java/spliterators/part1/exercise/RectangleSpliteratorTest.java b/src/test/java/spliterators/part1/exercise/RectangleSpliteratorTest.java new file mode 100644 index 0000000..48a9f96 --- /dev/null +++ b/src/test/java/spliterators/part1/exercise/RectangleSpliteratorTest.java @@ -0,0 +1,42 @@ +package spliterators.part1.exercise; + +import org.junit.Test; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class RectangleSpliteratorTest { + + private int[][] getRandomArray(int count, int length) { + final int[][] result = new int[count][length]; + + for (int i = 0; i < count; i++) + for (int j = 0; j < length; j++) + result[i][j] = j; + + return result; + } + + @Test + public void parallelAndSeqGiveSameResults() { + final int[][] randomArray = getRandomArray(4, 4); + + long count = StreamSupport.stream(new RectangleSpliterator(randomArray), true) + .count(); + long count2 = StreamSupport.stream(new RectangleSpliterator(randomArray), true) + .skip(7) + .count(); + int n = 7; + List result2 = StreamSupport.stream(new RectangleSpliterator(randomArray), true) + .skip(n) + .collect(Collectors.toList()); + + assertThat(count, is(16L)); + assertThat(count2, is(9L)); + assertThat(result2.get(0), is(randomArray[0][n % randomArray[0].length])); + } +} \ No newline at end of file diff --git a/src/test/java/spliterators/part2/exercise/ZipWithIndexDoubleSpliteratorTest.java b/src/test/java/spliterators/part2/exercise/ZipWithIndexDoubleSpliteratorTest.java new file mode 100644 index 0000000..364d57f --- /dev/null +++ b/src/test/java/spliterators/part2/exercise/ZipWithIndexDoubleSpliteratorTest.java @@ -0,0 +1,49 @@ +package spliterators.part2.exercise; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +import static java.util.stream.Collectors.toList; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertThat; + +public class ZipWithIndexDoubleSpliteratorTest { + private double[] getRandomArray(int length) { + final double[] result = new double[length]; + + for (int i = 0; i < length; i++) + result[i] = ThreadLocalRandom.current().nextDouble(); + + + return result; + } + + @Test + public void comparePaired() { + final double[] randomArray = getRandomArray(1000); + + final List result1 = + Stream.iterate( + new IndexedDoublePair(0, randomArray[0]), + p -> new IndexedDoublePair(p.getIndex() + 1, randomArray[p.getIndex() + 1])) + .limit(randomArray.length) + .skip(1) + .collect(toList()); + + final List result2 = + StreamSupport.stream( + new ZipWithIndexDoubleSpliterator(Arrays.spliterator(randomArray)), true) + .skip(1) + .map(p -> new IndexedDoublePair(p.getIndex() + 1, p.getValue())) + .map(p -> new IndexedDoublePair(p.getIndex() - 1, p.getValue())) + .collect(toList()); + + assertThat(result1, equalTo(result2)); + } + +} \ No newline at end of file From 8605c7c89a9e326783598db1dd34d7c40f7ca03a Mon Sep 17 00:00:00 2001 From: Michael-Georg Date: Mon, 17 Apr 2017 01:05:14 +0300 Subject: [PATCH 2/2] fixed remarks and added test for ZipWithIndexDoubleSpliterator --- .../part1/exercise/RectangleSpliterator.java | 18 +++++------ .../ZipWithIndexDoubleSpliterator.java | 10 ++++-- .../ZipWithIndexDoubleSpliteratorTest.java | 32 +++++++++++++++++-- 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/src/main/java/spliterators/part1/exercise/RectangleSpliterator.java b/src/main/java/spliterators/part1/exercise/RectangleSpliterator.java index dc4f035..b17bf9b 100755 --- a/src/main/java/spliterators/part1/exercise/RectangleSpliterator.java +++ b/src/main/java/spliterators/part1/exercise/RectangleSpliterator.java @@ -47,18 +47,16 @@ public long estimateSize() { @Override public boolean tryAdvance(IntConsumer action) { - if (startInnerInclusive < array[startOuterInclusive].length) { - action.accept(array[startOuterInclusive][startInnerInclusive]); - startInnerInclusive ++; - return true; - } else if (startOuterInclusive < endOuterExclusive-1) { + if (startInnerInclusive >= array[startOuterInclusive].length) { startInnerInclusive = 0; - ++startOuterInclusive; - action.accept(array[startOuterInclusive][startInnerInclusive]); - startInnerInclusive++; - return true; - } else + startOuterInclusive++; + } + if (startOuterInclusive >= endOuterExclusive) return false; + + action.accept(array[startOuterInclusive][startInnerInclusive]); + startInnerInclusive++; + return true; } } diff --git a/src/main/java/spliterators/part2/exercise/ZipWithIndexDoubleSpliterator.java b/src/main/java/spliterators/part2/exercise/ZipWithIndexDoubleSpliterator.java index cb934a2..09167f6 100755 --- a/src/main/java/spliterators/part2/exercise/ZipWithIndexDoubleSpliterator.java +++ b/src/main/java/spliterators/part2/exercise/ZipWithIndexDoubleSpliterator.java @@ -40,13 +40,19 @@ public void forEachRemaining(Consumer action) { @Override public Spliterator trySplit() { if (inner.hasCharacteristics(SUBSIZED)) { - return new ZipWithIndexDoubleSpliterator(currentIndex++, inner.trySplit()); + OfDouble ofDouble = this.inner.trySplit(); + if (ofDouble == null) + return null; + ZipWithIndexDoubleSpliterator result = + new ZipWithIndexDoubleSpliterator(currentIndex, ofDouble); + currentIndex += ofDouble.estimateSize(); + return result; } else return super.trySplit(); } @Override public long estimateSize() { - return currentIndex; + return currentIndex; } } diff --git a/src/test/java/spliterators/part2/exercise/ZipWithIndexDoubleSpliteratorTest.java b/src/test/java/spliterators/part2/exercise/ZipWithIndexDoubleSpliteratorTest.java index 364d57f..a201f29 100644 --- a/src/test/java/spliterators/part2/exercise/ZipWithIndexDoubleSpliteratorTest.java +++ b/src/test/java/spliterators/part2/exercise/ZipWithIndexDoubleSpliteratorTest.java @@ -9,6 +9,7 @@ import java.util.stream.StreamSupport; import static java.util.stream.Collectors.toList; +import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsEqual.equalTo; import static org.junit.Assert.assertThat; @@ -32,13 +33,13 @@ public void comparePaired() { new IndexedDoublePair(0, randomArray[0]), p -> new IndexedDoublePair(p.getIndex() + 1, randomArray[p.getIndex() + 1])) .limit(randomArray.length) - .skip(1) + .skip(2) .collect(toList()); final List result2 = StreamSupport.stream( new ZipWithIndexDoubleSpliterator(Arrays.spliterator(randomArray)), true) - .skip(1) + .skip(2) .map(p -> new IndexedDoublePair(p.getIndex() + 1, p.getValue())) .map(p -> new IndexedDoublePair(p.getIndex() - 1, p.getValue())) .collect(toList()); @@ -46,4 +47,31 @@ public void comparePaired() { assertThat(result1, equalTo(result2)); } + @Test + public void elementsSum() throws Exception { + final double[] array = getDoublesArr(100); + + double sum = StreamSupport.stream(new ZipWithIndexDoubleSpliterator(Arrays.spliterator(array)), true) + .mapToDouble(IndexedDoublePair::getValue) + .sum(); + assertThat(sum, is(100.0)); + } + + @Test + public void elementsSumAfterSkip() throws Exception { + final double[] array = getDoublesArr(100); + + double sum = StreamSupport.stream(new ZipWithIndexDoubleSpliterator(Arrays.spliterator(array)), true) + .mapToDouble(IndexedDoublePair::getValue) + .skip(10) + .sum(); + assertThat(sum, is(90.0)); + } + + private double[] getDoublesArr(int length) { + final double[] array = new double[length]; + for (int i = 0; i < length; i++) + array[i] = 1; + return array; + } } \ No newline at end of file