Fix issues in Spliterators code

This commit is contained in:
Alexey Andreev 2019-12-09 11:53:40 +03:00
parent dd255f9da0
commit e064457fe7
3 changed files with 68 additions and 27 deletions

View File

@ -57,7 +57,8 @@ public interface TSpliterator<T> {
throw new IllegalStateException(); throw new IllegalStateException();
} }
public interface OfPrimitive<T, C, S extends OfPrimitive<T, C, S>> { interface OfPrimitive<T, C, S extends OfPrimitive<T, C, S>> extends TSpliterator<T> {
@Override
S trySplit(); S trySplit();
boolean tryAdvance(C action); boolean tryAdvance(C action);
@ -69,11 +70,13 @@ public interface TSpliterator<T> {
} }
} }
public interface OfInt extends OfPrimitive<Integer, IntConsumer, OfInt> { interface OfInt extends OfPrimitive<Integer, IntConsumer, OfInt> {
@Override
default boolean tryAdvance(Consumer<? super Integer> action) { default boolean tryAdvance(Consumer<? super Integer> action) {
return tryAdvance((IntConsumer) action::accept); return tryAdvance((IntConsumer) action::accept);
} }
@Override
default void forEachRemaining(Consumer<? super Integer> action) { default void forEachRemaining(Consumer<? super Integer> action) {
while (tryAdvance(action)) { while (tryAdvance(action)) {
// continue // continue
@ -81,11 +84,13 @@ public interface TSpliterator<T> {
} }
} }
public interface OfLong extends OfPrimitive<Long, LongConsumer, OfLong> { interface OfLong extends OfPrimitive<Long, LongConsumer, OfLong> {
@Override
default boolean tryAdvance(Consumer<? super Long> action) { default boolean tryAdvance(Consumer<? super Long> action) {
return tryAdvance((LongConsumer) action::accept); return tryAdvance((LongConsumer) action::accept);
} }
@Override
default void forEachRemaining(Consumer<? super Long> action) { default void forEachRemaining(Consumer<? super Long> action) {
while (tryAdvance(action)) { while (tryAdvance(action)) {
// continue // continue
@ -93,11 +98,13 @@ public interface TSpliterator<T> {
} }
} }
public interface OfDouble extends OfPrimitive<Double, DoubleConsumer, OfDouble> { interface OfDouble extends OfPrimitive<Double, DoubleConsumer, OfDouble> {
@Override
default boolean tryAdvance(Consumer<? super Double> action) { default boolean tryAdvance(Consumer<? super Double> action) {
return tryAdvance((DoubleConsumer) action::accept); return tryAdvance((DoubleConsumer) action::accept);
} }
@Override
default void forEachRemaining(Consumer<? super Double> action) { default void forEachRemaining(Consumer<? super Double> action) {
while (tryAdvance(action)) { while (tryAdvance(action)) {
// continue // continue

View File

@ -35,8 +35,9 @@ public class TSpliterators {
return false; return false;
} }
action.accept((T) array[index]); @SuppressWarnings("unchecked")
index++; T e = (T) array[index++];
action.accept(e);
return true; return true;
} }
@ -47,7 +48,7 @@ public class TSpliterators {
@Override @Override
public long estimateSize() { public long estimateSize() {
return array.length; return array.length - index;
} }
@Override @Override
@ -57,8 +58,9 @@ public class TSpliterators {
}; };
} }
@SuppressWarnings("unchecked")
public static <T> TSpliterator<T> spliterator(Collection<? extends T> c, int characteristics) { public static <T> TSpliterator<T> spliterator(Collection<? extends T> c, int characteristics) {
return ((TCollection) c).spliterator(); return ((TCollection<T>) c).spliterator();
} }
public static TSpliterator.OfInt spliterator(int[] array, int additionalCharacteristics) { public static TSpliterator.OfInt spliterator(int[] array, int additionalCharacteristics) {
@ -78,18 +80,26 @@ public class TSpliterators {
@Override @Override
public boolean tryAdvance(IntConsumer action) { public boolean tryAdvance(IntConsumer action) {
if (index < toIndex) { if (index < toIndex) {
action.accept(array[index]); action.accept(array[index++]);
index++;
return true; return true;
} else { } else {
return false; return false;
} }
} }
@Override
public long estimateSize() {
return toIndex - index;
}
@Override
public int characteristics() {
return TSpliterator.SIZED;
}
}; };
} }
public static <T> TSpliterator<T> spliterator(Iterator<? extends T> iterator, public static <T> TSpliterator<T> spliterator(Iterator<? extends T> iterator, long size, int characteristics) {
long size, int characteristics) {
return new TSpliterator<T>() { return new TSpliterator<T>() {
@Override @Override
public boolean tryAdvance(Consumer<? super T> action) { public boolean tryAdvance(Consumer<? super T> action) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2015 Alexey Andreev. * Copyright 2019 Alexey Andreev.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -23,46 +23,59 @@ import static org.junit.Assert.assertTrue;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.IntConsumer; import java.util.function.IntConsumer;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith;
import org.teavm.junit.TeaVMTestRunner;
@RunWith(TeaVMTestRunner.class)
public class SpliteratorsTest { public class SpliteratorsTest {
@Test @Test
public void intSpliterator() { public void intSpliterator() {
int[] values = {1, 2, 3, 4, 5}; int[] values = { 1, 2, 3, 4, 5 };
TSpliterator.OfInt spliterator = TSpliterators.spliterator(values, 0, 5, 0); Spliterator.OfInt spliterator = Spliterators.spliterator(values, 0, 5, 0);
assertEquals(5L, spliterator.estimateSize());
List<Integer> collected = new ArrayList<>(); List<Integer> collected = new ArrayList<>();
IntConsumer collector = value -> collected.add((Integer) value); IntConsumer collector = collected::add;
assertTrue(spliterator.tryAdvance(collector)); assertTrue(spliterator.tryAdvance(collector));
assertEquals(4L, spliterator.estimateSize());
assertEquals(Arrays.asList(1), collected);
assertTrue(spliterator.tryAdvance(collector)); assertTrue(spliterator.tryAdvance(collector));
assertTrue(spliterator.tryAdvance(collector)); assertTrue(spliterator.tryAdvance(collector));
assertTrue(spliterator.tryAdvance(collector)); assertTrue(spliterator.tryAdvance(collector));
assertTrue(spliterator.tryAdvance(collector)); assertTrue(spliterator.tryAdvance(collector));
assertFalse(spliterator.tryAdvance(collector)); assertFalse(spliterator.tryAdvance(collector));
assertEquals(0L, spliterator.estimateSize());
assertEquals(Arrays.asList(1, 2, 3, 4, 5), collected); assertEquals(Arrays.asList(1, 2, 3, 4, 5), collected);
} }
@Test @Test
public void intSpliteratorWithSubRange() { public void intSpliteratorWithSubRange() {
int[] values = {1, 2, 3, 4, 5}; int[] values = { 1, 2, 3, 4, 5 };
TSpliterator.OfInt spliterator = TSpliterators.spliterator(values, 1, 4, 0); Spliterator.OfInt spliterator = Spliterators.spliterator(values, 1, 4, 0);
assertEquals(3L, spliterator.estimateSize());
List<Integer> collected = new ArrayList<>(); List<Integer> collected = new ArrayList<>();
IntConsumer collector = value -> collected.add((Integer) value); IntConsumer collector = collected::add;
assertTrue(spliterator.tryAdvance(collector)); assertTrue(spliterator.tryAdvance(collector));
assertTrue(spliterator.tryAdvance(collector)); assertTrue(spliterator.tryAdvance(collector));
assertTrue(spliterator.tryAdvance(collector)); assertTrue(spliterator.tryAdvance(collector));
assertFalse(spliterator.tryAdvance(collector)); assertFalse(spliterator.tryAdvance(collector));
assertEquals(0L, spliterator.estimateSize());
assertEquals(Arrays.asList(2, 3, 4), collected); assertEquals(Arrays.asList(2, 3, 4), collected);
} }
@ -70,20 +83,31 @@ public class SpliteratorsTest {
public void spliteratorFromIterator() { public void spliteratorFromIterator() {
List<Integer> values = Arrays.asList(1, 2, 3); List<Integer> values = Arrays.asList(1, 2, 3);
TSpliterator<Integer> spliterator = TSpliterators.spliterator(values.iterator(), Spliterator<Integer> spliterator = Spliterators.spliterator(values.iterator(), values.size(), 0);
values.size(), 0);
assertEquals(3L, spliterator.estimateSize()); assertEquals(3L, spliterator.estimateSize());
List<Integer> collected = new ArrayList<>();
Consumer<Integer> collector = collected::add;
assertTrue(spliterator.tryAdvance(collector));
assertTrue(spliterator.tryAdvance(collector));
assertTrue(spliterator.tryAdvance(collector));
assertFalse(spliterator.tryAdvance(collector));
assertEquals(3L, spliterator.estimateSize());
assertEquals(Arrays.asList(1, 2, 3), collected);
} }
@Test @Test
public void spliteratorFromObjectArray() { public void spliteratorFromObjectArray() {
Object[] array = {1, 2, 3, 4}; Object[] array = { 1, 2, 3, 4 };
TSpliterator<Integer> spliterator = TSpliterators.spliterator(array, 0); Spliterator<Integer> spliterator = Spliterators.spliterator(array, 0);
assertEquals(4L, spliterator.estimateSize());
List<Object> collected = new ArrayList<>(); List<Object> collected = new ArrayList<>();
Consumer<Object> collector = value -> collected.add(value); Consumer<Object> collector = collected::add;
spliterator.tryAdvance(collector); spliterator.tryAdvance(collector);
spliterator.tryAdvance(collector); spliterator.tryAdvance(collector);
@ -92,7 +116,7 @@ public class SpliteratorsTest {
spliterator.tryAdvance(collector); spliterator.tryAdvance(collector);
spliterator.tryAdvance(collector); spliterator.tryAdvance(collector);
assertArrayEquals(new Object[] {1, 2, 9, 4}, array); assertArrayEquals(new Object[] { 1, 2, 9, 4 }, collected.toArray());
assertEquals(4L, spliterator.estimateSize()); assertEquals(0, spliterator.estimateSize());
} }
} }