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();
}
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();
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) {
return tryAdvance((IntConsumer) action::accept);
}
@Override
default void forEachRemaining(Consumer<? super Integer> action) {
while (tryAdvance(action)) {
// 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) {
return tryAdvance((LongConsumer) action::accept);
}
@Override
default void forEachRemaining(Consumer<? super Long> action) {
while (tryAdvance(action)) {
// 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) {
return tryAdvance((DoubleConsumer) action::accept);
}
@Override
default void forEachRemaining(Consumer<? super Double> action) {
while (tryAdvance(action)) {
// continue

View File

@ -35,8 +35,9 @@ public class TSpliterators {
return false;
}
action.accept((T) array[index]);
index++;
@SuppressWarnings("unchecked")
T e = (T) array[index++];
action.accept(e);
return true;
}
@ -47,7 +48,7 @@ public class TSpliterators {
@Override
public long estimateSize() {
return array.length;
return array.length - index;
}
@Override
@ -57,8 +58,9 @@ public class TSpliterators {
};
}
@SuppressWarnings("unchecked")
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) {
@ -66,7 +68,7 @@ public class TSpliterators {
}
public static TSpliterator.OfInt spliterator(int[] array, int fromIndex, int toIndex,
int additionalCharacteristics) {
int additionalCharacteristics) {
return new TSpliterator.OfInt() {
int index = fromIndex;
@ -78,18 +80,26 @@ public class TSpliterators {
@Override
public boolean tryAdvance(IntConsumer action) {
if (index < toIndex) {
action.accept(array[index]);
index++;
action.accept(array[index++]);
return true;
} else {
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,
long size, int characteristics) {
public static <T> TSpliterator<T> spliterator(Iterator<? extends T> iterator, long size, int characteristics) {
return new TSpliterator<T>() {
@Override
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");
* 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.Arrays;
import java.util.List;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;
import java.util.function.IntConsumer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.teavm.junit.TeaVMTestRunner;
@RunWith(TeaVMTestRunner.class)
public class SpliteratorsTest {
@Test
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<>();
IntConsumer collector = value -> collected.add((Integer) value);
IntConsumer collector = collected::add;
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));
assertFalse(spliterator.tryAdvance(collector));
assertEquals(0L, spliterator.estimateSize());
assertEquals(Arrays.asList(1, 2, 3, 4, 5), collected);
}
@Test
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<>();
IntConsumer collector = value -> collected.add((Integer) value);
IntConsumer collector = collected::add;
assertTrue(spliterator.tryAdvance(collector));
assertTrue(spliterator.tryAdvance(collector));
assertTrue(spliterator.tryAdvance(collector));
assertFalse(spliterator.tryAdvance(collector));
assertEquals(0L, spliterator.estimateSize());
assertEquals(Arrays.asList(2, 3, 4), collected);
}
@ -70,20 +83,31 @@ public class SpliteratorsTest {
public void spliteratorFromIterator() {
List<Integer> values = Arrays.asList(1, 2, 3);
TSpliterator<Integer> spliterator = TSpliterators.spliterator(values.iterator(),
values.size(), 0);
Spliterator<Integer> spliterator = Spliterators.spliterator(values.iterator(), values.size(), 0);
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
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<>();
Consumer<Object> collector = value -> collected.add(value);
Consumer<Object> collector = collected::add;
spliterator.tryAdvance(collector);
spliterator.tryAdvance(collector);
@ -92,7 +116,7 @@ public class SpliteratorsTest {
spliterator.tryAdvance(collector);
spliterator.tryAdvance(collector);
assertArrayEquals(new Object[] {1, 2, 9, 4}, array);
assertEquals(4L, spliterator.estimateSize());
assertArrayEquals(new Object[] { 1, 2, 9, 4 }, collected.toArray());
assertEquals(0, spliterator.estimateSize());
}
}