diff --git a/src/main/java/spliterators/part3/exercise/ZipWithArraySpliterator.java b/src/main/java/spliterators/part3/exercise/ZipWithArraySpliterator.java index 292137e..adcefba 100755 --- a/src/main/java/spliterators/part3/exercise/ZipWithArraySpliterator.java +++ b/src/main/java/spliterators/part3/exercise/ZipWithArraySpliterator.java @@ -1,48 +1,80 @@ package spliterators.part3.exercise; +import java.util.Comparator; import java.util.Spliterator; import java.util.Spliterators; import java.util.function.Consumer; public class ZipWithArraySpliterator extends Spliterators.AbstractSpliterator> { - private final Spliterator inner; private final B[] array; + private int currentIndex; + private int endIndex; public ZipWithArraySpliterator(Spliterator inner, B[] array) { - super(Long.MAX_VALUE, 0); // FIXME: - // TODO - throw new UnsupportedOperationException(); + this(inner, array, 0, array.length); + } + + public ZipWithArraySpliterator(Spliterator inner, B[] array, int startIndex, int endIndex) { + super(array.length, inner.characteristics()); + this.inner = inner; + this.array = array; + this.currentIndex = startIndex; + this.endIndex = endIndex; } @Override public int characteristics() { - // TODO - throw new UnsupportedOperationException(); + return inner.characteristics() + | NONNULL + | SIZED; } @Override public boolean tryAdvance(Consumer> action) { - // TODO - throw new UnsupportedOperationException(); + return (currentIndex < endIndex + && inner.tryAdvance(a -> action.accept(new Pair(a, array[currentIndex++])))); } @Override public void forEachRemaining(Consumer> action) { - // TODO - throw new UnsupportedOperationException(); + while (currentIndex < endIndex) { + if (!inner.tryAdvance(a -> action.accept(new Pair(a, array[currentIndex++])))) { + return; + } + } } @Override public Spliterator> trySplit() { - // TODO - throw new UnsupportedOperationException(); + Spliterator splitInner = this.inner.trySplit(); + if (splitInner == null || array.length - currentIndex <= 1) { + return null; + } + + if (inner.hasCharacteristics(SUBSIZED)) { + int newStart = currentIndex; + currentIndex += splitInner.estimateSize(); + int newEnd = currentIndex < array.length ? currentIndex : array.length; + + return new ZipWithArraySpliterator<>(splitInner, array, newStart, newEnd); + } else { + return super.trySplit(); + } } @Override public long estimateSize() { - // TODO - throw new UnsupportedOperationException(); + return endIndex - currentIndex; + } + + @Override + public Comparator> getComparator() { + if (inner.hasCharacteristics(SORTED)) { + return (p1, p2) -> inner.getComparator().compare(p1.getA(), p2.getA()); + } else { + throw new IllegalStateException(); + } } } diff --git a/src/test/java/spliterators/part3/exercise/ZipWithArraySpliteratorTest.java b/src/test/java/spliterators/part3/exercise/ZipWithArraySpliteratorTest.java new file mode 100644 index 0000000..b279793 --- /dev/null +++ b/src/test/java/spliterators/part3/exercise/ZipWithArraySpliteratorTest.java @@ -0,0 +1,61 @@ +package spliterators.part3.exercise; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.StreamSupport; + +import static org.junit.Assert.*; + + +public class ZipWithArraySpliteratorTest { + + private List listWithLessSize = new ArrayList<>(Arrays.asList(0, 1, 2, 3, 4, 5)); + private List listWithSameSize = new ArrayList<>(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)); + private List listWithMoreSize = new ArrayList<>(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)); + + private Integer[] array = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + @Test + public void testCount() { + final long expectedLess = listWithLessSize.size(); + final long actualLess = StreamSupport + .stream(new ZipWithArraySpliterator<>(listWithLessSize.spliterator(), array), true) + .count(); + assertEquals(expectedLess, actualLess); + + final long expectedSame = listWithSameSize.size(); + final long actualSame = StreamSupport + .stream(new ZipWithArraySpliterator<>(listWithSameSize.spliterator(), array), true) + .count(); + assertEquals(expectedSame, actualSame); + + final long expectedMore = array.length; + final long actualMore = StreamSupport + .stream(new ZipWithArraySpliterator<>(listWithMoreSize.spliterator(), array), true) + .count(); + assertEquals(expectedMore, actualMore); + } + + @Test + public void testSkip() { + long actual = StreamSupport + .stream(new ZipWithArraySpliterator<>(listWithSameSize.spliterator(), array), true) + .skip(2) + .mapToInt(Pair::getA) + .sum(); + assertEquals(44, actual); + } + + @Test + public void testLimit() { + long actual = StreamSupport + .stream(new ZipWithArraySpliterator<>(listWithSameSize.spliterator(), array), true) + .limit(4) + .mapToInt(Pair::getA) + .sum(); + assertEquals(6, actual); + } +} \ No newline at end of file