diff --git a/src/main/java/spliterators/part1/exercise/RectangleSpliterator.java b/src/main/java/spliterators/part1/exercise/RectangleSpliterator.java index 678f4f5..b17bf9b 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,34 @@ 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) { + startInnerInclusive = 0; + 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 deb4867..09167f6 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,36 @@ 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)) { + 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() { - // 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..a201f29 --- /dev/null +++ b/src/test/java/spliterators/part2/exercise/ZipWithIndexDoubleSpliteratorTest.java @@ -0,0 +1,77 @@ +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.Is.is; +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(2) + .collect(toList()); + + final List result2 = + StreamSupport.stream( + new ZipWithIndexDoubleSpliterator(Arrays.spliterator(randomArray)), true) + .skip(2) + .map(p -> new IndexedDoublePair(p.getIndex() + 1, p.getValue())) + .map(p -> new IndexedDoublePair(p.getIndex() - 1, p.getValue())) + .collect(toList()); + + 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