From e064457fe7b8cac33ae63e0b1c978543c7ea306e Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Mon, 9 Dec 2019 11:53:40 +0300 Subject: [PATCH] Fix issues in Spliterators code --- .../classlib/java/util/TSpliterator.java | 15 ++++-- .../classlib/java/util/TSpliterators.java | 28 ++++++---- .../classlib/java/util/SpliteratorsTest.java | 52 ++++++++++++++----- 3 files changed, 68 insertions(+), 27 deletions(-) rename {classlib => tests}/src/test/java/org/teavm/classlib/java/util/SpliteratorsTest.java (59%) diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/TSpliterator.java b/classlib/src/main/java/org/teavm/classlib/java/util/TSpliterator.java index 99342e42c..311773200 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/util/TSpliterator.java +++ b/classlib/src/main/java/org/teavm/classlib/java/util/TSpliterator.java @@ -57,7 +57,8 @@ public interface TSpliterator { throw new IllegalStateException(); } - public interface OfPrimitive> { + interface OfPrimitive> extends TSpliterator { + @Override S trySplit(); boolean tryAdvance(C action); @@ -69,11 +70,13 @@ public interface TSpliterator { } } - public interface OfInt extends OfPrimitive { + interface OfInt extends OfPrimitive { + @Override default boolean tryAdvance(Consumer action) { return tryAdvance((IntConsumer) action::accept); } + @Override default void forEachRemaining(Consumer action) { while (tryAdvance(action)) { // continue @@ -81,11 +84,13 @@ public interface TSpliterator { } } - public interface OfLong extends OfPrimitive { + interface OfLong extends OfPrimitive { + @Override default boolean tryAdvance(Consumer action) { return tryAdvance((LongConsumer) action::accept); } + @Override default void forEachRemaining(Consumer action) { while (tryAdvance(action)) { // continue @@ -93,11 +98,13 @@ public interface TSpliterator { } } - public interface OfDouble extends OfPrimitive { + interface OfDouble extends OfPrimitive { + @Override default boolean tryAdvance(Consumer action) { return tryAdvance((DoubleConsumer) action::accept); } + @Override default void forEachRemaining(Consumer action) { while (tryAdvance(action)) { // continue diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/TSpliterators.java b/classlib/src/main/java/org/teavm/classlib/java/util/TSpliterators.java index 0b16d2dd3..7fc2a4b84 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/util/TSpliterators.java +++ b/classlib/src/main/java/org/teavm/classlib/java/util/TSpliterators.java @@ -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 TSpliterator spliterator(Collection c, int characteristics) { - return ((TCollection) c).spliterator(); + return ((TCollection) 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 TSpliterator spliterator(Iterator iterator, - long size, int characteristics) { + public static TSpliterator spliterator(Iterator iterator, long size, int characteristics) { return new TSpliterator() { @Override public boolean tryAdvance(Consumer action) { diff --git a/classlib/src/test/java/org/teavm/classlib/java/util/SpliteratorsTest.java b/tests/src/test/java/org/teavm/classlib/java/util/SpliteratorsTest.java similarity index 59% rename from classlib/src/test/java/org/teavm/classlib/java/util/SpliteratorsTest.java rename to tests/src/test/java/org/teavm/classlib/java/util/SpliteratorsTest.java index a5c786e09..4ca6896e9 100644 --- a/classlib/src/test/java/org/teavm/classlib/java/util/SpliteratorsTest.java +++ b/tests/src/test/java/org/teavm/classlib/java/util/SpliteratorsTest.java @@ -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 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 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 values = Arrays.asList(1, 2, 3); - TSpliterator spliterator = TSpliterators.spliterator(values.iterator(), - values.size(), 0); + Spliterator spliterator = Spliterators.spliterator(values.iterator(), values.size(), 0); assertEquals(3L, spliterator.estimateSize()); + + List collected = new ArrayList<>(); + Consumer 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 spliterator = TSpliterators.spliterator(array, 0); + Spliterator spliterator = Spliterators.spliterator(array, 0); + assertEquals(4L, spliterator.estimateSize()); List collected = new ArrayList<>(); - Consumer collector = value -> collected.add(value); + Consumer 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()); } }