diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/TIterable.java b/classlib/src/main/java/org/teavm/classlib/java/lang/TIterable.java index c99aecfb9..96df87610 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/TIterable.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/TIterable.java @@ -15,13 +15,47 @@ */ package org.teavm.classlib.java.lang; +import java.util.function.Consumer; import org.teavm.classlib.java.util.TIterator; +import org.teavm.classlib.java.util.TSpliterator; -/** - * - * @author Alexey Andreev - * @param type this collection returns. - */ public interface TIterable { TIterator iterator(); + + default TSpliterator spliterator() { + TIterator iterator = iterator(); + return new TSpliterator() { + @Override + public boolean tryAdvance(Consumer action) { + if (iterator.hasNext()) { + action.accept(iterator.next()); + return true; + } else { + return false; + } + } + + @Override + public void forEachRemaining(Consumer action) { + while (iterator.hasNext()) { + action.accept(iterator.next()); + } + } + + @Override + public TSpliterator trySplit() { + return null; + } + + @Override + public long estimateSize() { + return -1; + } + + @Override + public int characteristics() { + return 0; + } + }; + } } diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/TAbstractCollection.java b/classlib/src/main/java/org/teavm/classlib/java/util/TAbstractCollection.java index f82bc39fd..401bb8801 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/util/TAbstractCollection.java +++ b/classlib/src/main/java/org/teavm/classlib/java/util/TAbstractCollection.java @@ -19,11 +19,6 @@ import java.lang.reflect.Array; import org.teavm.classlib.java.lang.TObject; import org.teavm.classlib.java.lang.TUnsupportedOperationException; -/** - * - * @author Alexey Andreev - * @param - */ public abstract class TAbstractCollection extends TObject implements TCollection { protected TAbstractCollection() { } diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/TAbstractSet.java b/classlib/src/main/java/org/teavm/classlib/java/util/TAbstractSet.java index db2eb6543..1ad4c8a8e 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/util/TAbstractSet.java +++ b/classlib/src/main/java/org/teavm/classlib/java/util/TAbstractSet.java @@ -15,11 +15,8 @@ */ package org.teavm.classlib.java.util; -/** - * - * @author Alexey Andreev - * @param - */ +import java.util.Arrays; + public abstract class TAbstractSet extends TAbstractCollection implements TSet { public TAbstractSet() { super(); @@ -45,4 +42,31 @@ public abstract class TAbstractSet extends TAbstractCollection implements } return modified; } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof TSet)) { + return false; + } + + TSet other = (TSet) obj; + if (size() != other.size()) { + return false; + } + + for (TIterator iter = other.iterator(); iter.hasNext();) { + if (!contains(iter.next())) { + return false; + } + } + return true; + } + + @Override + public int hashCode() { + return Arrays.hashCode(toArray()); + } } diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/TArrays.java b/classlib/src/main/java/org/teavm/classlib/java/util/TArrays.java index ded65c3aa..4a397b9ed 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/util/TArrays.java +++ b/classlib/src/main/java/org/teavm/classlib/java/util/TArrays.java @@ -29,6 +29,14 @@ import org.teavm.classlib.java.lang.TObject; import org.teavm.classlib.java.lang.TString; import org.teavm.classlib.java.lang.TStringBuilder; import org.teavm.classlib.java.lang.reflect.TArray; +import org.teavm.classlib.java.util.stream.TDoubleStream; +import org.teavm.classlib.java.util.stream.TIntStream; +import org.teavm.classlib.java.util.stream.TLongStream; +import org.teavm.classlib.java.util.stream.TStream; +import org.teavm.classlib.java.util.stream.doubleimpl.TArrayDoubleStreamImpl; +import org.teavm.classlib.java.util.stream.impl.TArrayStreamImpl; +import org.teavm.classlib.java.util.stream.intimpl.TArrayIntStreamImpl; +import org.teavm.classlib.java.util.stream.longimpl.TArrayLongStreamImpl; public class TArrays extends TObject { public static char[] copyOf(char[] array, int length) { @@ -1519,7 +1527,7 @@ public class TArrays extends TObject { public static TString deepToString(Object[] a) { TStringBuilder sb = new TStringBuilder(); - deepToString(a, sb, new TArrayList()); + deepToString(a, sb, new TArrayList<>()); return TString.wrap(sb.toString()); } @@ -1548,4 +1556,48 @@ public class TArrays extends TObject { out.append(TObject.wrap(a)); } } + + public static TStream stream(T[] array) { + return new TArrayStreamImpl<>(array, 0, array.length); + } + + public static TStream stream(T[] array, int startInclusive, int endExclusive) { + if (startInclusive < 0 || endExclusive < startInclusive || endExclusive > array.length) { + throw new ArrayIndexOutOfBoundsException(); + } + return new TArrayStreamImpl<>(array, startInclusive, endExclusive); + } + + public static TIntStream stream(int[] array) { + return new TArrayIntStreamImpl(array, 0, array.length); + } + + public static TIntStream stream(int[] array, int startInclusive, int endExclusive) { + if (startInclusive < 0 || endExclusive < startInclusive || endExclusive > array.length) { + throw new ArrayIndexOutOfBoundsException(); + } + return new TArrayIntStreamImpl(array, startInclusive, endExclusive); + } + + public static TLongStream stream(long[] array) { + return new TArrayLongStreamImpl(array, 0, array.length); + } + + public static TLongStream stream(long[] array, int startInclusive, int endExclusive) { + if (startInclusive < 0 || endExclusive < startInclusive || endExclusive > array.length) { + throw new ArrayIndexOutOfBoundsException(); + } + return new TArrayLongStreamImpl(array, startInclusive, endExclusive); + } + + public static TDoubleStream stream(double[] array) { + return new TArrayDoubleStreamImpl(array, 0, array.length); + } + + public static TDoubleStream stream(double[] array, int startInclusive, int endExclusive) { + if (startInclusive < 0 || endExclusive < startInclusive || endExclusive > array.length) { + throw new ArrayIndexOutOfBoundsException(); + } + return new TArrayDoubleStreamImpl(array, startInclusive, endExclusive); + } } diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/TCollection.java b/classlib/src/main/java/org/teavm/classlib/java/util/TCollection.java index 425813213..150284a10 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/util/TCollection.java +++ b/classlib/src/main/java/org/teavm/classlib/java/util/TCollection.java @@ -15,13 +15,12 @@ */ package org.teavm.classlib.java.util; +import java.util.Spliterator; import org.teavm.classlib.java.lang.TIterable; +import org.teavm.classlib.java.util.stream.TStream; +import org.teavm.classlib.java.util.stream.impl.TSpliteratorOverCollection; +import org.teavm.classlib.java.util.stream.impl.TStreamOverSpliterator; -/** - * - * @author Alexey Andreev - * @param - */ public interface TCollection extends TIterable { int size(); @@ -46,4 +45,14 @@ public interface TCollection extends TIterable { boolean retainAll(TCollection c); void clear(); + + @Override + default TSpliterator spliterator() { + return new TSpliteratorOverCollection<>(this); + } + + @SuppressWarnings("unchecked") + default TStream stream() { + return new TStreamOverSpliterator<>((Spliterator) spliterator()); + } } diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/TIterator.java b/classlib/src/main/java/org/teavm/classlib/java/util/TIterator.java index bb50abc3b..5cd43b8cd 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/util/TIterator.java +++ b/classlib/src/main/java/org/teavm/classlib/java/util/TIterator.java @@ -15,15 +15,18 @@ */ package org.teavm.classlib.java.util; -/** - * - * @author Alexey Andreev - * @param - */ +import java.util.function.Consumer; + public interface TIterator { boolean hasNext(); E next(); void remove(); + + default void forEachRemaining(Consumer action) { + while (hasNext()) { + action.accept(next()); + } + } } diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/TList.java b/classlib/src/main/java/org/teavm/classlib/java/util/TList.java index 0c6ac7c51..0b8351d26 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/util/TList.java +++ b/classlib/src/main/java/org/teavm/classlib/java/util/TList.java @@ -15,11 +15,6 @@ */ package org.teavm.classlib.java.util; -/** - * - * @author Alexey Andreev - * @param - */ public interface TList extends TCollection { boolean addAll(int index, TCollection c); @@ -40,4 +35,8 @@ public interface TList extends TCollection { TListIterator listIterator(int index); TList subList(int fromIndex, int toIndex); + + default void sort(TComparator c) { + TCollections.sort(this, c); + } } diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/TOptionalDouble.java b/classlib/src/main/java/org/teavm/classlib/java/util/TOptionalDouble.java new file mode 100644 index 000000000..82b04a6bc --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/TOptionalDouble.java @@ -0,0 +1,96 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util; + +import java.util.NoSuchElementException; +import java.util.function.DoubleConsumer; +import java.util.function.DoubleSupplier; +import java.util.function.Supplier; + +public class TOptionalDouble { + private static TOptionalDouble emptyInstance; + private final double value; + + private TOptionalDouble(double value) { + this.value = value; + } + + @SuppressWarnings("unchecked") + public static TOptionalDouble empty() { + if (emptyInstance == null) { + emptyInstance = new TOptionalDouble(0); + } + return emptyInstance; + } + + public static TOptionalDouble of(double value) { + return new TOptionalDouble(value); + } + + public double getAsDouble() { + if (this == emptyInstance) { + throw new NoSuchElementException(); + } + return value; + } + + public boolean isPresent() { + return this != emptyInstance; + } + + public void ifPresent(DoubleConsumer consumer) { + if (this != emptyInstance) { + consumer.accept(value); + } + } + + public double orElse(double other) { + return this != emptyInstance ? value : other; + } + + public double orElseGet(DoubleSupplier other) { + return this != emptyInstance ? value : other.getAsDouble(); + } + + public double orElseThrow(Supplier exceptionSupplier) throws X { + if (!isPresent()) { + throw exceptionSupplier.get(); + } + return value; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof TOptionalDouble)) { + return false; + } + + return ((TOptionalDouble) obj).value == value; + } + + @Override + public int hashCode() { + return Double.hashCode(value); + } + + @Override + public String toString() { + return isPresent() ? "OptionalDouble.of(" + value + ")" : "OptionalDouble.empty()"; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/TOptionalInt.java b/classlib/src/main/java/org/teavm/classlib/java/util/TOptionalInt.java new file mode 100644 index 000000000..4f92ef5ec --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/TOptionalInt.java @@ -0,0 +1,96 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util; + +import java.util.NoSuchElementException; +import java.util.function.IntConsumer; +import java.util.function.IntSupplier; +import java.util.function.Supplier; + +public class TOptionalInt { + private static TOptionalInt emptyInstance; + private final int value; + + private TOptionalInt(int value) { + this.value = value; + } + + @SuppressWarnings("unchecked") + public static TOptionalInt empty() { + if (emptyInstance == null) { + emptyInstance = new TOptionalInt(0); + } + return emptyInstance; + } + + public static TOptionalInt of(int value) { + return new TOptionalInt(value); + } + + public int getAsInt() { + if (this == emptyInstance) { + throw new NoSuchElementException(); + } + return value; + } + + public boolean isPresent() { + return this != emptyInstance; + } + + public void ifPresent(IntConsumer consumer) { + if (this != emptyInstance) { + consumer.accept(value); + } + } + + public int orElse(int other) { + return this != emptyInstance ? value : other; + } + + public int orElseGet(IntSupplier other) { + return this != emptyInstance ? value : other.getAsInt(); + } + + public int orElseThrow(Supplier exceptionSupplier) throws X { + if (!isPresent()) { + throw exceptionSupplier.get(); + } + return value; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof TOptionalInt)) { + return false; + } + + return ((TOptionalInt) obj).value == value; + } + + @Override + public int hashCode() { + return value; + } + + @Override + public String toString() { + return isPresent() ? "OptionalInt.of(" + value + ")" : "OptionalInt.empty()"; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/TOptionalLong.java b/classlib/src/main/java/org/teavm/classlib/java/util/TOptionalLong.java new file mode 100644 index 000000000..a6f7d58d5 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/TOptionalLong.java @@ -0,0 +1,96 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util; + +import java.util.NoSuchElementException; +import java.util.function.LongConsumer; +import java.util.function.LongSupplier; +import java.util.function.Supplier; + +public class TOptionalLong { + private static TOptionalLong emptyInstance; + private final long value; + + private TOptionalLong(long value) { + this.value = value; + } + + @SuppressWarnings("unchecked") + public static TOptionalLong empty() { + if (emptyInstance == null) { + emptyInstance = new TOptionalLong(0); + } + return emptyInstance; + } + + public static TOptionalLong of(long value) { + return new TOptionalLong(value); + } + + public long getAsLong() { + if (this == emptyInstance) { + throw new NoSuchElementException(); + } + return value; + } + + public boolean isPresent() { + return this != emptyInstance; + } + + public void ifPresent(LongConsumer consumer) { + if (this != emptyInstance) { + consumer.accept(value); + } + } + + public long orElse(long other) { + return this != emptyInstance ? value : other; + } + + public long orElseGet(LongSupplier other) { + return this != emptyInstance ? value : other.getAsLong(); + } + + public long orElseThrow(Supplier exceptionSupplier) throws X { + if (!isPresent()) { + throw exceptionSupplier.get(); + } + return value; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof TOptionalLong)) { + return false; + } + + return ((TOptionalLong) obj).value == value; + } + + @Override + public int hashCode() { + return Long.hashCode(value); + } + + @Override + public String toString() { + return isPresent() ? "OptionalLong.of(" + value + ")" : "OptionalLong.empty()"; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/TPrimitiveIterator.java b/classlib/src/main/java/org/teavm/classlib/java/util/TPrimitiveIterator.java new file mode 100644 index 000000000..cb4ab4985 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/TPrimitiveIterator.java @@ -0,0 +1,95 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util; + +import java.util.Iterator; +import java.util.function.Consumer; +import java.util.function.DoubleConsumer; +import java.util.function.IntConsumer; +import java.util.function.LongConsumer; + +public interface TPrimitiveIterator extends Iterator { + void forEachRemaining(S action); + + interface OfInt extends TPrimitiveIterator { + @Override + default void forEachRemaining(Consumer action) { + while (hasNext()) { + action.accept(nextInt()); + } + } + + @Override + default void forEachRemaining(IntConsumer action) { + while (hasNext()) { + action.accept(nextInt()); + } + } + + int nextInt(); + + @Override + default Integer next() { + return nextInt(); + } + } + + interface OfLong extends TPrimitiveIterator { + @Override + default void forEachRemaining(Consumer action) { + while (hasNext()) { + action.accept(nextLong()); + } + } + + @Override + default void forEachRemaining(LongConsumer action) { + while (hasNext()) { + action.accept(nextLong()); + } + } + + long nextLong(); + + @Override + default Long next() { + return nextLong(); + } + } + + interface OfDouble extends TPrimitiveIterator { + @Override + default void forEachRemaining(Consumer action) { + while (hasNext()) { + action.accept(nextDouble()); + } + } + + @Override + default void forEachRemaining(DoubleConsumer action) { + while (hasNext()) { + action.accept(nextDouble()); + } + } + + double nextDouble(); + + @Override + default Double next() { + return nextDouble(); + } + } +} 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 new file mode 100644 index 000000000..c3b551bae --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/TSpliterator.java @@ -0,0 +1,107 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util; + +import java.util.Comparator; +import java.util.function.Consumer; +import java.util.function.DoubleConsumer; +import java.util.function.IntConsumer; +import java.util.function.LongConsumer; + +public interface TSpliterator { + int ORDERED = 16; + int DISTINCT = 1; + int SORTED = 4; + int SIZED = 64; + int NONNULL = 256; + int IMMUTABLE = 1024; + int CONCURRENT = 4096; + int SUBSIZED = 16384; + + boolean tryAdvance(Consumer action); + + default void forEachRemaining(Consumer action) { + while (tryAdvance(action)) { + // just repeat + } + } + + TSpliterator trySplit(); + + long estimateSize(); + + default long getExactSizeIfKnown() { + return (characteristics() & SIZED) != 0 ? estimateSize() : -1; + } + + int characteristics(); + + default boolean hasCharacteristics(int characteristics) { + return (characteristics() & characteristics) == characteristics; + } + + default Comparator getComparator() { + throw new IllegalStateException(); + } + + interface OfPrimitive> { + S trySplit(); + + boolean tryAdvance(C action); + + default void forEachRemaining(C action) { + while (tryAdvance(action)) { + // continue + } + } + } + + interface OfInt extends OfPrimitive { + default boolean tryAdvance(Consumer action) { + return tryAdvance((IntConsumer) action::accept); + } + + default void forEachRemaining(Consumer action) { + while (tryAdvance(action)) { + // continue + } + } + } + + interface OfLong extends OfPrimitive { + default boolean tryAdvance(Consumer action) { + return tryAdvance((LongConsumer) action::accept); + } + + default void forEachRemaining(Consumer action) { + while (tryAdvance(action)) { + // continue + } + } + } + + interface OfDouble extends OfPrimitive { + default boolean tryAdvance(Consumer action) { + return tryAdvance((DoubleConsumer) action::accept); + } + + default void forEachRemaining(Consumer action) { + while (tryAdvance(action)) { + // continue + } + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/function/TLongBinaryOperator.java b/classlib/src/main/java/org/teavm/classlib/java/util/function/TLongBinaryOperator.java new file mode 100644 index 000000000..5a6302934 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/function/TLongBinaryOperator.java @@ -0,0 +1,21 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.function; + +@FunctionalInterface +public interface TLongBinaryOperator { + long applyAsLong(long left, long right); +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/function/TLongConsumer.java b/classlib/src/main/java/org/teavm/classlib/java/util/function/TLongConsumer.java new file mode 100644 index 000000000..55503e4fb --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/function/TLongConsumer.java @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.function; + +@FunctionalInterface +public interface TLongConsumer { + void accept(long value); + + default TLongConsumer andThen(TLongConsumer after) { + return v -> { + accept(v); + after.accept(v); + }; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/function/TLongFunction.java b/classlib/src/main/java/org/teavm/classlib/java/util/function/TLongFunction.java new file mode 100644 index 000000000..4d7e0d9cb --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/function/TLongFunction.java @@ -0,0 +1,21 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.function; + +@FunctionalInterface +public interface TLongFunction { + R apply(long value); +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/function/TLongPredicate.java b/classlib/src/main/java/org/teavm/classlib/java/util/function/TLongPredicate.java new file mode 100644 index 000000000..d22f87e6a --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/function/TLongPredicate.java @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.function; + +@FunctionalInterface +public interface TLongPredicate { + boolean test(long value); + + default TLongPredicate and(TLongPredicate other) { + return v -> test(v) && other.test(v); + } + + default TLongPredicate negate() { + return v -> !test(v); + } + + default TLongPredicate or(TLongPredicate other) { + return v -> test(v) || other.test(v); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/function/TLongSupplier.java b/classlib/src/main/java/org/teavm/classlib/java/util/function/TLongSupplier.java new file mode 100644 index 000000000..b8cf6d6f1 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/function/TLongSupplier.java @@ -0,0 +1,21 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.function; + +@FunctionalInterface +public interface TLongSupplier { + long getAsLong(); +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/function/TLongToDoubleFunction.java b/classlib/src/main/java/org/teavm/classlib/java/util/function/TLongToDoubleFunction.java new file mode 100644 index 000000000..c14dd6bbe --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/function/TLongToDoubleFunction.java @@ -0,0 +1,21 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.function; + +@FunctionalInterface +public interface TLongToDoubleFunction { + double applyAsDouble(long value); +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/function/TLongToIntFunction.java b/classlib/src/main/java/org/teavm/classlib/java/util/function/TLongToIntFunction.java new file mode 100644 index 000000000..ef0387015 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/function/TLongToIntFunction.java @@ -0,0 +1,21 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.function; + +@FunctionalInterface +public interface TLongToIntFunction { + int applyAsInt(long value); +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/function/TLongUnaryOperator.java b/classlib/src/main/java/org/teavm/classlib/java/util/function/TLongUnaryOperator.java new file mode 100644 index 000000000..0cb5e6d16 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/function/TLongUnaryOperator.java @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.function; + +@FunctionalInterface +public interface TLongUnaryOperator { + long applyAsLong(long operand); + + default TLongUnaryOperator compose(TLongUnaryOperator before) { + return v -> applyAsLong(before.applyAsLong(v)); + } + + default TLongUnaryOperator andThen(TLongUnaryOperator after) { + return v -> after.applyAsLong(applyAsLong(v)); + } + + static TLongUnaryOperator identity() { + return v -> v; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/TBaseStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/TBaseStream.java new file mode 100644 index 000000000..d3af3fdbc --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/TBaseStream.java @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream; + +import java.util.Iterator; +import java.util.Spliterator; + +public interface TBaseStream> extends AutoCloseable { + Iterator iterator(); + + Spliterator spliterator(); + + boolean isParallel(); + + S sequential(); + + S parallel(); + + S unordered(); + + S onClose(Runnable closeHandler); +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/TCollector.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/TCollector.java new file mode 100644 index 000000000..0561aff3e --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/TCollector.java @@ -0,0 +1,54 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream; + +import java.util.Arrays; +import java.util.EnumSet; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.Supplier; + +public interface TCollector { + enum Characteristics { + CONCURRENT, + UNORDERED, + IDENTITY_FINISH + } + + Supplier supplier(); + + BiConsumer accumulator(); + + BinaryOperator combiner(); + + Function finisher(); + + Set characteristics(); + + static TCollector of(Supplier supplier, BiConsumer accumulator, BinaryOperator combiner, + Characteristics... characteristics) { + return of(supplier, accumulator, combiner, x -> x, characteristics); + } + + static TCollector of(Supplier supplier, BiConsumer accumulator, + BinaryOperator combiner, Function finisher, Characteristics... characteristics) { + EnumSet characteristicsSet = EnumSet.noneOf(Characteristics.class); + characteristicsSet.addAll(Arrays.asList(characteristics)); + return new TCollectorImpl<>(supplier, accumulator, combiner, finisher, characteristicsSet); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/TCollectorImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/TCollectorImpl.java new file mode 100644 index 000000000..d078a765a --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/TCollectorImpl.java @@ -0,0 +1,65 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream; + +import java.util.EnumSet; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.Supplier; + +class TCollectorImpl implements TCollector { + private Supplier supplier; + private BiConsumer accumulator; + private BinaryOperator combiner; + private Function finisher; + private EnumSet characteristics; + + TCollectorImpl(Supplier supplier, BiConsumer accumulator, BinaryOperator combiner, + Function finisher, EnumSet characteristics) { + this.supplier = supplier; + this.accumulator = accumulator; + this.combiner = combiner; + this.finisher = finisher; + this.characteristics = characteristics; + } + + @Override + public Supplier supplier() { + return supplier; + } + + @Override + public BiConsumer accumulator() { + return accumulator; + } + + @Override + public BinaryOperator combiner() { + return combiner; + } + + @Override + public Function finisher() { + return finisher; + } + + @Override + public Set characteristics() { + return characteristics; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/TCollectors.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/TCollectors.java new file mode 100644 index 000000000..543bd9359 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/TCollectors.java @@ -0,0 +1,72 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.BinaryOperator; +import java.util.function.Supplier; + +public final class TCollectors { + private TCollectors() { + } + + public static > TCollector toCollection(Supplier collectionFactory) { + return TCollector.of(collectionFactory, Collection::add, (a, b) -> { + a.addAll(b); + return a; + }); + } + + public static TCollector> toList() { + return toCollection(ArrayList::new); + } + + public static TCollector> toSet() { + return toCollection(HashSet::new); + } + + public static TCollector joining() { + return TCollector.of(StringBuilder::new, StringBuilder::append, StringBuilder::append, + StringBuilder::toString); + } + + public static TCollector joining(CharSequence delimiter) { + return joining(delimiter, "", ""); + } + + public static TCollector joining(CharSequence delimiter, CharSequence prefix, + CharSequence suffix) { + BiConsumer accumulator = (sb, item) -> { + if (sb.length() > 0) { + sb.append(delimiter); + } + sb.append(item); + }; + BinaryOperator combiner = (a, b) -> { + if (a.length() > 0) { + a.append(delimiter); + } + return a.append(b); + }; + return TCollector.of(StringBuilder::new, accumulator, combiner, + sb -> sb.insert(0, prefix).append(suffix).toString()); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/TDoubleStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/TDoubleStream.java new file mode 100644 index 000000000..f801fa8e3 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/TDoubleStream.java @@ -0,0 +1,147 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream; + +import java.util.OptionalDouble; +import java.util.PrimitiveIterator; +import java.util.Spliterator; +import java.util.function.BiConsumer; +import java.util.function.DoubleBinaryOperator; +import java.util.function.DoubleConsumer; +import java.util.function.DoubleFunction; +import java.util.function.DoublePredicate; +import java.util.function.DoubleSupplier; +import java.util.function.DoubleToIntFunction; +import java.util.function.DoubleToLongFunction; +import java.util.function.DoubleUnaryOperator; +import java.util.function.ObjDoubleConsumer; +import java.util.function.Supplier; +import org.teavm.classlib.java.util.stream.doubleimpl.TArrayDoubleStreamImpl; +import org.teavm.classlib.java.util.stream.doubleimpl.TDoubleStreamBuilder; +import org.teavm.classlib.java.util.stream.doubleimpl.TEmptyDoubleStreamImpl; +import org.teavm.classlib.java.util.stream.doubleimpl.TGenerateDoubleStream; +import org.teavm.classlib.java.util.stream.doubleimpl.TGenericConcatDoubleStream; +import org.teavm.classlib.java.util.stream.doubleimpl.TIterateDoubleStream; +import org.teavm.classlib.java.util.stream.doubleimpl.TSimpleDoubleStreamImpl; +import org.teavm.classlib.java.util.stream.doubleimpl.TSingleDoubleStreamImpl; +import org.teavm.classlib.java.util.stream.doubleimpl.TSpecializedConcatDoubleStream; + +public interface TDoubleStream extends TBaseStream { + interface Builder { + void accept(double t); + + default Builder add(double t) { + accept(t); + return this; + } + + TDoubleStream build(); + } + + TDoubleStream filter(DoublePredicate predicate); + + TDoubleStream map(DoubleUnaryOperator mapper); + + TStream mapToObj(DoubleFunction mapper); + + TIntStream mapToInt(DoubleToIntFunction mapper); + + TLongStream mapToLong(DoubleToLongFunction mapper); + + TDoubleStream flatMap(DoubleFunction mapper); + + TDoubleStream distinct(); + + TDoubleStream sorted(); + + TDoubleStream peek(DoubleConsumer action); + + TDoubleStream limit(long maxSize); + + TDoubleStream skip(long n); + + void forEach(DoubleConsumer action); + + void forEachOrdered(DoubleConsumer action); + + double[] toArray(); + + double reduce(double identity, DoubleBinaryOperator accumulator); + + OptionalDouble reduce(DoubleBinaryOperator op); + + R collect(Supplier supplier, ObjDoubleConsumer accumulator, BiConsumer combiner); + + double sum(); + + OptionalDouble min(); + + OptionalDouble max(); + + long count(); + + OptionalDouble average(); + + boolean anyMatch(DoublePredicate predicate); + + boolean allMatch(DoublePredicate predicate); + + boolean noneMatch(DoublePredicate predicate); + + OptionalDouble findFirst(); + + OptionalDouble findAny(); + + TStream boxed(); + + @Override + PrimitiveIterator.OfDouble iterator(); + + @Override + Spliterator.OfDouble spliterator(); + + static TDoubleStream.Builder builder() { + return new TDoubleStreamBuilder(); + } + + static TDoubleStream empty() { + return new TEmptyDoubleStreamImpl(); + } + + static TDoubleStream of(double t) { + return new TSingleDoubleStreamImpl(t); + } + + static TDoubleStream of(double... values) { + return new TArrayDoubleStreamImpl(values, 0, values.length); + } + + static TDoubleStream iterate(double seed, DoubleUnaryOperator f) { + return new TIterateDoubleStream(seed, f); + } + + static TDoubleStream generate(DoubleSupplier s) { + return new TGenerateDoubleStream(s); + } + + static TDoubleStream concat(TDoubleStream a, TDoubleStream b) { + if (a instanceof TSimpleDoubleStreamImpl && b instanceof TSimpleDoubleStreamImpl) { + return new TSpecializedConcatDoubleStream((TSimpleDoubleStreamImpl) a, (TSimpleDoubleStreamImpl) b); + } else { + return new TGenericConcatDoubleStream(a, b); + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/TIntStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/TIntStream.java new file mode 100644 index 000000000..3f44e8cfe --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/TIntStream.java @@ -0,0 +1,161 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream; + +import java.util.OptionalDouble; +import java.util.OptionalInt; +import java.util.PrimitiveIterator; +import java.util.Spliterator; +import java.util.function.BiConsumer; +import java.util.function.IntBinaryOperator; +import java.util.function.IntConsumer; +import java.util.function.IntFunction; +import java.util.function.IntPredicate; +import java.util.function.IntSupplier; +import java.util.function.IntToDoubleFunction; +import java.util.function.IntToLongFunction; +import java.util.function.IntUnaryOperator; +import java.util.function.ObjIntConsumer; +import java.util.function.Supplier; +import org.teavm.classlib.java.util.stream.intimpl.TArrayIntStreamImpl; +import org.teavm.classlib.java.util.stream.intimpl.TEmptyIntStreamImpl; +import org.teavm.classlib.java.util.stream.intimpl.TGenerateIntStream; +import org.teavm.classlib.java.util.stream.intimpl.TGenericConcatIntStream; +import org.teavm.classlib.java.util.stream.intimpl.TIntStreamBuilder; +import org.teavm.classlib.java.util.stream.intimpl.TIterateIntStream; +import org.teavm.classlib.java.util.stream.intimpl.TRangeIntStream; +import org.teavm.classlib.java.util.stream.intimpl.TSimpleIntStreamImpl; +import org.teavm.classlib.java.util.stream.intimpl.TSingleIntStreamImpl; +import org.teavm.classlib.java.util.stream.intimpl.TSpecializedConcatIntStream; + +public interface TIntStream extends TBaseStream { + interface Builder { + void accept(int t); + + default Builder add(int t) { + accept(t); + return this; + } + + TIntStream build(); + } + + TIntStream filter(IntPredicate predicate); + + TIntStream map(IntUnaryOperator mapper); + + TStream mapToObj(IntFunction mapper); + + TLongStream mapToLong(IntToLongFunction mapper); + + TDoubleStream mapToDouble(IntToDoubleFunction mapper); + + TIntStream flatMap(IntFunction mapper); + + TIntStream distinct(); + + TIntStream sorted(); + + TIntStream peek(IntConsumer action); + + TIntStream limit(long maxSize); + + TIntStream skip(long n); + + void forEach(IntConsumer action); + + void forEachOrdered(IntConsumer action); + + int[] toArray(); + + int reduce(int identity, IntBinaryOperator accumulator); + + OptionalInt reduce(IntBinaryOperator op); + + R collect(Supplier supplier, ObjIntConsumer accumulator, BiConsumer combiner); + + int sum(); + + OptionalInt min(); + + OptionalInt max(); + + long count(); + + OptionalDouble average(); + + boolean anyMatch(IntPredicate predicate); + + boolean allMatch(IntPredicate predicate); + + boolean noneMatch(IntPredicate predicate); + + OptionalInt findFirst(); + + OptionalInt findAny(); + + TLongStream asLongStream(); + + TDoubleStream asDoubleStream(); + + TStream boxed(); + + @Override + PrimitiveIterator.OfInt iterator(); + + @Override + Spliterator.OfInt spliterator(); + + static Builder builder() { + return new TIntStreamBuilder(); + } + + static TIntStream empty() { + return new TEmptyIntStreamImpl(); + } + + static TIntStream of(int t) { + return new TSingleIntStreamImpl(t); + } + + static TIntStream of(int... values) { + return new TArrayIntStreamImpl(values, 0, values.length); + } + + static TIntStream iterate(int seed, IntUnaryOperator f) { + return new TIterateIntStream(seed, f); + } + + static TIntStream generate(IntSupplier s) { + return new TGenerateIntStream(s); + } + + static TIntStream range(int startInclusive, int endExclusive) { + return new TRangeIntStream(startInclusive, endExclusive); + } + + static TIntStream rangeClosed(int startInclusive, int endInclusive) { + return new TRangeIntStream(startInclusive, endInclusive + 1); + } + + static TIntStream concat(TIntStream a, TIntStream b) { + if (a instanceof TSimpleIntStreamImpl && b instanceof TSimpleIntStreamImpl) { + return new TSpecializedConcatIntStream((TSimpleIntStreamImpl) a, (TSimpleIntStreamImpl) b); + } else { + return new TGenericConcatIntStream(a, b); + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/TLongStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/TLongStream.java new file mode 100644 index 000000000..2b32a18db --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/TLongStream.java @@ -0,0 +1,159 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream; + +import java.util.OptionalDouble; +import java.util.OptionalLong; +import java.util.PrimitiveIterator; +import java.util.Spliterator; +import java.util.function.BiConsumer; +import java.util.function.LongBinaryOperator; +import java.util.function.LongConsumer; +import java.util.function.LongFunction; +import java.util.function.LongPredicate; +import java.util.function.LongSupplier; +import java.util.function.LongToDoubleFunction; +import java.util.function.LongToIntFunction; +import java.util.function.LongUnaryOperator; +import java.util.function.ObjLongConsumer; +import java.util.function.Supplier; +import org.teavm.classlib.java.util.stream.longimpl.TArrayLongStreamImpl; +import org.teavm.classlib.java.util.stream.longimpl.TEmptyLongStreamImpl; +import org.teavm.classlib.java.util.stream.longimpl.TGenerateLongStream; +import org.teavm.classlib.java.util.stream.longimpl.TGenericConcatLongStream; +import org.teavm.classlib.java.util.stream.longimpl.TIterateLongStream; +import org.teavm.classlib.java.util.stream.longimpl.TLongStreamBuilder; +import org.teavm.classlib.java.util.stream.longimpl.TRangeLongStream; +import org.teavm.classlib.java.util.stream.longimpl.TSimpleLongStreamImpl; +import org.teavm.classlib.java.util.stream.longimpl.TSingleLongStreamImpl; +import org.teavm.classlib.java.util.stream.longimpl.TSpecializedConcatLongStream; + +public interface TLongStream extends TBaseStream { + interface Builder { + void accept(long t); + + default Builder add(long t) { + accept(t); + return this; + } + + TLongStream build(); + } + + TLongStream filter(LongPredicate predicate); + + TLongStream map(LongUnaryOperator mapper); + + TStream mapToObj(LongFunction mapper); + + TIntStream mapToInt(LongToIntFunction mapper); + + TDoubleStream mapToDouble(LongToDoubleFunction mapper); + + TLongStream flatMap(LongFunction mapper); + + TLongStream distinct(); + + TLongStream sorted(); + + TLongStream peek(LongConsumer action); + + TLongStream limit(long maxSize); + + TLongStream skip(long n); + + void forEach(LongConsumer action); + + void forEachOrdered(LongConsumer action); + + long[] toArray(); + + long reduce(long identity, LongBinaryOperator accumulator); + + OptionalLong reduce(LongBinaryOperator op); + + R collect(Supplier supplier, ObjLongConsumer accumulator, BiConsumer combiner); + + long sum(); + + OptionalLong min(); + + OptionalLong max(); + + long count(); + + OptionalDouble average(); + + boolean anyMatch(LongPredicate predicate); + + boolean allMatch(LongPredicate predicate); + + boolean noneMatch(LongPredicate predicate); + + OptionalLong findFirst(); + + OptionalLong findAny(); + + TDoubleStream asDoubleStream(); + + TStream boxed(); + + @Override + PrimitiveIterator.OfLong iterator(); + + @Override + Spliterator.OfLong spliterator(); + + static Builder builder() { + return new TLongStreamBuilder(); + } + + static TLongStream empty() { + return new TEmptyLongStreamImpl(); + } + + static TLongStream of(long t) { + return new TSingleLongStreamImpl(t); + } + + static TLongStream of(long... values) { + return new TArrayLongStreamImpl(values, 0, values.length); + } + + static TLongStream iterate(long seed, LongUnaryOperator f) { + return new TIterateLongStream(seed, f); + } + + static TLongStream generate(LongSupplier s) { + return new TGenerateLongStream(s); + } + + static TLongStream range(long startInclusive, long endExclusive) { + return new TRangeLongStream(startInclusive, endExclusive); + } + + static TLongStream rangeClosed(long startInclusive, long endInclusive) { + return new TRangeLongStream(startInclusive, endInclusive + 1); + } + + static TLongStream concat(TLongStream a, TLongStream b) { + if (a instanceof TSimpleLongStreamImpl && b instanceof TSimpleLongStreamImpl) { + return new TSpecializedConcatLongStream((TSimpleLongStreamImpl) a, (TSimpleLongStreamImpl) b); + } else { + return new TGenericConcatLongStream(a, b); + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/TStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/TStream.java new file mode 100644 index 000000000..38ed37c98 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/TStream.java @@ -0,0 +1,151 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream; + +import java.util.Comparator; +import java.util.Optional; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.BinaryOperator; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.IntFunction; +import java.util.function.Predicate; +import java.util.function.Supplier; +import java.util.function.ToDoubleFunction; +import java.util.function.ToIntFunction; +import java.util.function.ToLongFunction; +import java.util.function.UnaryOperator; +import org.teavm.classlib.java.util.stream.impl.TArrayStreamImpl; +import org.teavm.classlib.java.util.stream.impl.TEmptyStreamImpl; +import org.teavm.classlib.java.util.stream.impl.TGenerateStream; +import org.teavm.classlib.java.util.stream.impl.TGenericConcatStream; +import org.teavm.classlib.java.util.stream.impl.TIterateStream; +import org.teavm.classlib.java.util.stream.impl.TSimpleStreamImpl; +import org.teavm.classlib.java.util.stream.impl.TSingleStreamImpl; +import org.teavm.classlib.java.util.stream.impl.TSpecializedConcatStream; +import org.teavm.classlib.java.util.stream.impl.TStreamBuilder; + +public interface TStream extends TBaseStream> { + interface Builder { + void accept(T t); + + default Builder add(T t) { + accept(t); + return this; + } + + TStream build(); + } + + TStream filter(Predicate predicate); + + TStream map(Function mapper); + + TIntStream mapToInt(ToIntFunction mapper); + + TLongStream mapToLong(ToLongFunction mapper); + + TDoubleStream mapToDouble(ToDoubleFunction mapper); + + TStream flatMap(Function> mapper); + + TIntStream flatMapToInt(Function mapper); + + TLongStream flatMapToLong(Function mapper); + + TDoubleStream flatMapToDouble(Function mapper); + + TStream distinct(); + + TStream sorted(); + + TStream sorted(Comparator comparator); + + TStream peek(Consumer action); + + TStream limit(long maxSize); + + TStream skip(long n); + + void forEach(Consumer action); + + void forEachOrdered(Consumer action); + + Object[] toArray(); + + A[] toArray(IntFunction generator); + + T reduce(T identity, BinaryOperator accumulator); + + Optional reduce(BinaryOperator accumulator); + + U reduce(U identity, BiFunction accumulator, BinaryOperator combiner); + + R collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner); + + R collect(TCollector collector); + + Optional min(Comparator comparator); + + Optional max(Comparator comparator); + + long count(); + + boolean anyMatch(Predicate predicate); + + boolean allMatch(Predicate predicate); + + boolean noneMatch(Predicate predicate); + + Optional findFirst(); + + Optional findAny(); + + static TStream.Builder builder() { + return new TStreamBuilder<>(); + } + + static TStream empty() { + return new TEmptyStreamImpl<>(); + } + + static TStream of(T t) { + return new TSingleStreamImpl<>(t); + } + + @SafeVarargs + static TStream of(T... values) { + return new TArrayStreamImpl<>(values, 0, values.length); + } + + static TStream iterate(T seed, UnaryOperator f) { + return new TIterateStream<>(seed, f); + } + + static TStream generate(Supplier s) { + return new TGenerateStream<>(s); + } + + @SuppressWarnings("unchecked") + static TStream concat(TStream a, TStream b) { + if (a instanceof TSimpleStreamImpl && b instanceof TSimpleStreamImpl) { + return new TSpecializedConcatStream<>((TSimpleStreamImpl) a, (TSimpleStreamImpl) b); + } else { + return new TGenericConcatStream<>(a, b); + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/TStreamSupport.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/TStreamSupport.java new file mode 100644 index 000000000..3da611c91 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/TStreamSupport.java @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream; + +import java.util.Spliterator; +import org.teavm.classlib.java.util.stream.impl.TStreamOverSpliterator; + +public final class TStreamSupport { + private TStreamSupport() { + } + + public static TStream stream(Spliterator spliterator, boolean parallel) { + return new TStreamOverSpliterator<>(spliterator); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TArrayDoubleStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TArrayDoubleStreamImpl.java new file mode 100644 index 000000000..8cba18314 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TArrayDoubleStreamImpl.java @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.function.DoublePredicate; + +public class TArrayDoubleStreamImpl extends TSimpleDoubleStreamImpl { + private double[] array; + private int index; + private int end; + private int size; + + public TArrayDoubleStreamImpl(double[] array, int start, int end) { + this.array = array; + index = start; + this.end = end; + size = end - start; + } + + @Override + public boolean next(DoublePredicate consumer) { + while (index < end) { + if (!consumer.test(array[index++])) { + break; + } + } + return index < end; + } + + @Override + protected int estimateSize() { + return size; + } + + @Override + public long count() { + return size; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TAverageDoubleConsumer.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TAverageDoubleConsumer.java new file mode 100644 index 000000000..40b083ba5 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TAverageDoubleConsumer.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.function.DoublePredicate; + +public class TAverageDoubleConsumer implements DoublePredicate { + double sum; + int count; + + @Override + public boolean test(double t) { + sum += t; + count++; + return true; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TBoxedDoubleStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TBoxedDoubleStream.java new file mode 100644 index 000000000..bee853dba --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TBoxedDoubleStream.java @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.function.Predicate; +import org.teavm.classlib.java.util.stream.impl.TSimpleStreamImpl; + +public class TBoxedDoubleStream extends TSimpleStreamImpl { + private TSimpleDoubleStreamImpl source; + + public TBoxedDoubleStream(TSimpleDoubleStreamImpl source) { + this.source = source; + } + + @Override + public boolean next(Predicate consumer) { + return source.next(consumer::test); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TCloseHandlingDoubleStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TCloseHandlingDoubleStream.java new file mode 100644 index 000000000..eabc4a9f6 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TCloseHandlingDoubleStream.java @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.function.DoublePredicate; + +public class TCloseHandlingDoubleStream extends TSimpleDoubleStreamImpl { + private TSimpleDoubleStreamImpl innerStream; + private Runnable closeHandler; + + public TCloseHandlingDoubleStream(TSimpleDoubleStreamImpl innerStream, Runnable closeHandler) { + this.innerStream = innerStream; + this.closeHandler = closeHandler; + } + + @Override + public boolean next(DoublePredicate consumer) { + return innerStream.next(consumer); + } + + @Override + public void close() throws Exception { + RuntimeException previousException = null; + try { + closeHandler.run(); + } catch (RuntimeException e) { + previousException = e; + } + + try { + innerStream.close(); + } catch (RuntimeException e) { + if (previousException != null) { + e.addSuppressed(previousException); + } + throw e; + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TCountingDoubleConsumer.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TCountingDoubleConsumer.java new file mode 100644 index 000000000..9be001634 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TCountingDoubleConsumer.java @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.function.DoublePredicate; + +public class TCountingDoubleConsumer implements DoublePredicate { + int count; + + @Override + public boolean test(double t) { + count++; + return true; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TDistinctDoubleStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TDistinctDoubleStreamImpl.java new file mode 100644 index 000000000..f02631f67 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TDistinctDoubleStreamImpl.java @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.HashSet; +import java.util.Set; +import java.util.function.DoublePredicate; + +public class TDistinctDoubleStreamImpl extends TWrappingDoubleStreamImpl { + public TDistinctDoubleStreamImpl(TSimpleDoubleStreamImpl innerStream) { + super(innerStream); + } + + @Override + protected DoublePredicate wrap(DoublePredicate consumer) { + Set visited = new HashSet<>(); + return e -> { + if (!visited.add(e)) { + return true; + } + return consumer.test(e); + }; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TDoubleStreamBuilder.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TDoubleStreamBuilder.java new file mode 100644 index 000000000..f5a30e8b1 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TDoubleStreamBuilder.java @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.Arrays; +import org.teavm.classlib.java.util.stream.TDoubleStream; + +public class TDoubleStreamBuilder implements TDoubleStream.Builder { + private double[] elements = new double[4]; + private int size; + + @Override + public void accept(double t) { + if (size == elements.length) { + elements = Arrays.copyOf(elements, elements.length * 2); + } + elements[size++] = t; + } + + @Override + public TDoubleStream build() { + return new TArrayDoubleStreamImpl(elements, 0, size); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TEmptyDoubleStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TEmptyDoubleStreamImpl.java new file mode 100644 index 000000000..3b5a99d41 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TEmptyDoubleStreamImpl.java @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.function.DoublePredicate; + +public class TEmptyDoubleStreamImpl extends TSimpleDoubleStreamImpl { + @Override + public boolean next(DoublePredicate consumer) { + return false; + } + + @Override + protected int estimateSize() { + return 0; + } + + @Override + public long count() { + return 1; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TFilteringDoubleStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TFilteringDoubleStreamImpl.java new file mode 100644 index 000000000..bfad54d6d --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TFilteringDoubleStreamImpl.java @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.function.DoublePredicate; + +public class TFilteringDoubleStreamImpl extends TWrappingDoubleStreamImpl { + private DoublePredicate filter; + + public TFilteringDoubleStreamImpl(TSimpleDoubleStreamImpl innerStream, DoublePredicate filter) { + super(innerStream); + this.filter = filter; + } + + @Override + protected DoublePredicate wrap(DoublePredicate consumer) { + return t -> { + if (!filter.test(t)) { + return true; + } + return consumer.test(t); + }; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TFindFirstDoubleConsumer.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TFindFirstDoubleConsumer.java new file mode 100644 index 000000000..f7b01fc4b --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TFindFirstDoubleConsumer.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.function.DoublePredicate; + +public class TFindFirstDoubleConsumer implements DoublePredicate { + public double result; + boolean hasAny; + + @Override + public boolean test(double t) { + hasAny = true; + result = t; + return false; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TFlatMappingDoubleStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TFlatMappingDoubleStreamImpl.java new file mode 100644 index 000000000..984f951ba --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TFlatMappingDoubleStreamImpl.java @@ -0,0 +1,82 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.PrimitiveIterator; +import java.util.function.DoubleFunction; +import java.util.function.DoublePredicate; +import org.teavm.classlib.java.util.stream.TDoubleStream; + +public class TFlatMappingDoubleStreamImpl extends TSimpleDoubleStreamImpl { + private TSimpleDoubleStreamImpl sourceStream; + private TDoubleStream current; + private PrimitiveIterator.OfDouble iterator; + private DoubleFunction mapper; + private boolean done; + + public TFlatMappingDoubleStreamImpl(TSimpleDoubleStreamImpl sourceStream, + DoubleFunction mapper) { + this.sourceStream = sourceStream; + this.mapper = mapper; + } + + @Override + public boolean next(DoublePredicate consumer) { + while (true) { + if (current == null) { + if (done) { + return false; + } + boolean hasMore = sourceStream.next(e -> { + current = mapper.apply(e); + return false; + }); + if (!hasMore) { + done = true; + } + if (current == null) { + done = true; + return false; + } + } + if (current instanceof TSimpleDoubleStreamImpl) { + @SuppressWarnings("unchecked") + TSimpleDoubleStreamImpl castCurrent = (TSimpleDoubleStreamImpl) current; + if (castCurrent.next(consumer)) { + return true; + } + current = null; + } else { + iterator = current.iterator(); + while (iterator.hasNext()) { + double e = iterator.nextDouble(); + if (!consumer.test(e)) { + return true; + } + } + iterator = null; + current = null; + } + } + } + + @Override + public void close() throws Exception { + current = null; + iterator = null; + sourceStream.close(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TGenerateDoubleStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TGenerateDoubleStream.java new file mode 100644 index 000000000..adc5fc897 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TGenerateDoubleStream.java @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.function.DoublePredicate; +import java.util.function.DoubleSupplier; + +public class TGenerateDoubleStream extends TSimpleDoubleStreamImpl { + private DoubleSupplier s; + + public TGenerateDoubleStream(DoubleSupplier s) { + this.s = s; + } + + @Override + public boolean next(DoublePredicate consumer) { + while (consumer.test(s.getAsDouble())) { + // go on + } + return true; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TGenericConcatDoubleStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TGenericConcatDoubleStream.java new file mode 100644 index 000000000..afab1289f --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TGenericConcatDoubleStream.java @@ -0,0 +1,75 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.PrimitiveIterator; +import java.util.function.DoublePredicate; +import org.teavm.classlib.java.util.stream.TDoubleStream; + +public class TGenericConcatDoubleStream extends TSimpleDoubleStreamImpl { + TDoubleStream first; + TDoubleStream second; + PrimitiveIterator.OfDouble iterator; + boolean isSecond; + + public TGenericConcatDoubleStream(TDoubleStream first, TDoubleStream second) { + this.first = first; + this.second = second; + } + + @Override + public boolean next(DoublePredicate consumer) { + if (iterator == null) { + iterator = first.iterator(); + } + while (true) { + while (iterator.hasNext()) { + if (!consumer.test(iterator.nextDouble())) { + return true; + } + } + if (!isSecond) { + isSecond = true; + iterator = second.iterator(); + } else { + return false; + } + } + } + + @Override + public long count() { + return first.count() + second.count(); + } + + @Override + public void close() throws Exception { + Exception suppressed = null; + try { + first.close(); + } catch (Exception e) { + suppressed = e; + } + try { + second.close(); + } catch (Exception e) { + if (suppressed != null) { + e.addSuppressed(suppressed); + } + throw e; + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TIterateDoubleStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TIterateDoubleStream.java new file mode 100644 index 000000000..024049e39 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TIterateDoubleStream.java @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.function.DoublePredicate; +import java.util.function.DoubleUnaryOperator; + +public class TIterateDoubleStream extends TSimpleDoubleStreamImpl { + private double value; + private DoubleUnaryOperator f; + + public TIterateDoubleStream(double value, DoubleUnaryOperator f) { + this.value = value; + this.f = f; + } + + @Override + public boolean next(DoublePredicate consumer) { + while (true) { + double valueToReport = value; + value = f.applyAsDouble(value); + if (!consumer.test(valueToReport)) { + return true; + } + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TLimitingDoubleStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TLimitingDoubleStreamImpl.java new file mode 100644 index 000000000..58a64707e --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TLimitingDoubleStreamImpl.java @@ -0,0 +1,58 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.function.DoublePredicate; + +public class TLimitingDoubleStreamImpl extends TSimpleDoubleStreamImpl { + private TSimpleDoubleStreamImpl sourceStream; + private int limit; + private int remaining; + + public TLimitingDoubleStreamImpl(TSimpleDoubleStreamImpl sourceStream, int limit) { + this.sourceStream = sourceStream; + this.limit = limit; + remaining = limit; + } + + @Override + public boolean next(DoublePredicate consumer) { + if (remaining == 0) { + return false; + } + boolean result = sourceStream.next(e -> { + if (remaining-- == 0) { + return false; + } + return consumer.test(e); + }); + if (!result) { + remaining = 0; + } + return remaining > 0; + } + + @Override + protected int estimateSize() { + int sourceEstimation = sourceStream.estimateSize(); + return sourceEstimation < 0 ? limit : Math.min(limit, sourceEstimation); + } + + @Override + public void close() throws Exception { + sourceStream.close(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TMappingDoubleStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TMappingDoubleStreamImpl.java new file mode 100644 index 000000000..1c2d0dc8a --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TMappingDoubleStreamImpl.java @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.function.DoublePredicate; +import java.util.function.DoubleUnaryOperator; + +public class TMappingDoubleStreamImpl extends TWrappingDoubleStreamImpl { + private DoubleUnaryOperator mapper; + + public TMappingDoubleStreamImpl(TSimpleDoubleStreamImpl sourceStream, DoubleUnaryOperator mapper) { + super(sourceStream); + this.mapper = mapper; + } + + @Override + protected DoublePredicate wrap(DoublePredicate consumer) { + return t -> consumer.test(mapper.applyAsDouble(t)); + } + + @Override + public long count() { + return sourceStream.count(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TMappingToIntStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TMappingToIntStreamImpl.java new file mode 100644 index 000000000..82315e3ca --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TMappingToIntStreamImpl.java @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.function.DoubleToIntFunction; +import java.util.function.IntPredicate; +import org.teavm.classlib.java.util.stream.intimpl.TSimpleIntStreamImpl; + +public class TMappingToIntStreamImpl extends TSimpleIntStreamImpl { + private TSimpleDoubleStreamImpl source; + private DoubleToIntFunction mapper; + + public TMappingToIntStreamImpl(TSimpleDoubleStreamImpl source, DoubleToIntFunction mapper) { + this.source = source; + this.mapper = mapper; + } + + @Override + public boolean next(IntPredicate consumer) { + return source.next(e -> consumer.test(mapper.applyAsInt(e))); + } + + @Override + public void close() throws Exception { + source.close(); + } + + @Override + protected int estimateSize() { + return source.estimateSize(); + } + + @Override + public long count() { + return source.count(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TMappingToLongStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TMappingToLongStreamImpl.java new file mode 100644 index 000000000..af722602b --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TMappingToLongStreamImpl.java @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.function.DoubleToLongFunction; +import java.util.function.LongPredicate; +import org.teavm.classlib.java.util.stream.longimpl.TSimpleLongStreamImpl; + +public class TMappingToLongStreamImpl extends TSimpleLongStreamImpl { + private TSimpleDoubleStreamImpl source; + private DoubleToLongFunction mapper; + + public TMappingToLongStreamImpl(TSimpleDoubleStreamImpl source, DoubleToLongFunction mapper) { + this.source = source; + this.mapper = mapper; + } + + @Override + public boolean next(LongPredicate consumer) { + return source.next(e -> consumer.test(mapper.applyAsLong(e))); + } + + @Override + public void close() throws Exception { + source.close(); + } + + @Override + protected int estimateSize() { + return source.estimateSize(); + } + + @Override + public long count() { + return source.count(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TMappingToObjStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TMappingToObjStreamImpl.java new file mode 100644 index 000000000..947bed623 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TMappingToObjStreamImpl.java @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.function.DoubleFunction; +import java.util.function.Predicate; +import org.teavm.classlib.java.util.stream.impl.TSimpleStreamImpl; + +public class TMappingToObjStreamImpl extends TSimpleStreamImpl { + private TSimpleDoubleStreamImpl source; + private DoubleFunction mapper; + + public TMappingToObjStreamImpl(TSimpleDoubleStreamImpl source, DoubleFunction mapper) { + this.source = source; + this.mapper = mapper; + } + + @Override + public boolean next(Predicate consumer) { + return source.next(e -> consumer.test(mapper.apply(e))); + } + + @Override + public void close() throws Exception { + source.close(); + } + + @Override + protected int estimateSize() { + return source.estimateSize(); + } + + @Override + public long count() { + return source.count(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TPeekingDoubleStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TPeekingDoubleStreamImpl.java new file mode 100644 index 000000000..250e3cda0 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TPeekingDoubleStreamImpl.java @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.function.DoubleConsumer; +import java.util.function.DoublePredicate; + +public class TPeekingDoubleStreamImpl extends TWrappingDoubleStreamImpl { + private DoubleConsumer elementConsumer; + + public TPeekingDoubleStreamImpl(TSimpleDoubleStreamImpl sourceStream, DoubleConsumer elementConsumer) { + super(sourceStream); + this.elementConsumer = elementConsumer; + } + + @Override + protected DoublePredicate wrap(DoublePredicate consumer) { + return e -> { + elementConsumer.accept(e); + return consumer.test(e); + }; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TReducingDoubleConsumer.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TReducingDoubleConsumer.java new file mode 100644 index 000000000..cb5f8d6c1 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TReducingDoubleConsumer.java @@ -0,0 +1,42 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.function.DoubleBinaryOperator; +import java.util.function.DoublePredicate; + +class TReducingDoubleConsumer implements DoublePredicate { + private DoubleBinaryOperator accumulator; + double result; + boolean initialized; + + TReducingDoubleConsumer(DoubleBinaryOperator accumulator, double result, boolean initialized) { + this.accumulator = accumulator; + this.result = result; + this.initialized = initialized; + } + + @Override + public boolean test(double t) { + if (!initialized) { + result = t; + initialized = true; + } else { + result = accumulator.applyAsDouble(result, t); + } + return true; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TSimpleDoubleStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TSimpleDoubleStreamImpl.java new file mode 100644 index 000000000..e58e95fa6 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TSimpleDoubleStreamImpl.java @@ -0,0 +1,281 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.OptionalDouble; +import java.util.PrimitiveIterator; +import java.util.Spliterator; +import java.util.function.BiConsumer; +import java.util.function.DoubleBinaryOperator; +import java.util.function.DoubleConsumer; +import java.util.function.DoubleFunction; +import java.util.function.DoublePredicate; +import java.util.function.DoubleToIntFunction; +import java.util.function.DoubleToLongFunction; +import java.util.function.DoubleUnaryOperator; +import java.util.function.ObjDoubleConsumer; +import java.util.function.Supplier; +import org.teavm.classlib.java.util.stream.TDoubleStream; +import org.teavm.classlib.java.util.stream.TIntStream; +import org.teavm.classlib.java.util.stream.TLongStream; +import org.teavm.classlib.java.util.stream.TStream; + +public abstract class TSimpleDoubleStreamImpl implements TDoubleStream { + @Override + public TDoubleStream filter(DoublePredicate predicate) { + return new TFilteringDoubleStreamImpl(this, predicate); + } + + @Override + public TDoubleStream map(DoubleUnaryOperator mapper) { + return new TMappingDoubleStreamImpl(this, mapper); + } + + @Override + public TStream mapToObj(DoubleFunction mapper) { + return new TMappingToObjStreamImpl<>(this, mapper); + } + + @Override + public TIntStream mapToInt(DoubleToIntFunction mapper) { + return new TMappingToIntStreamImpl(this, mapper); + } + + @Override + public TLongStream mapToLong(DoubleToLongFunction mapper) { + return new TMappingToLongStreamImpl(this, mapper); + } + + @Override + public TDoubleStream flatMap(DoubleFunction mapper) { + return new TFlatMappingDoubleStreamImpl(this, mapper); + } + + @Override + public TDoubleStream distinct() { + return new TDistinctDoubleStreamImpl(this); + } + + @Override + public TDoubleStream sorted() { + double[] array = toArray(); + Arrays.sort(array); + return TDoubleStream.of(array); + } + + @Override + public TDoubleStream peek(DoubleConsumer action) { + return new TPeekingDoubleStreamImpl(this, action); + } + + @Override + public TDoubleStream limit(long maxSize) { + return new TLimitingDoubleStreamImpl(this, (int) maxSize); + } + + @Override + public TDoubleStream skip(long n) { + return new TSkippingDoubleStreamImpl(this, (int) n); + } + + @Override + public void forEach(DoubleConsumer action) { + forEachOrdered(action); + } + + @Override + public void forEachOrdered(DoubleConsumer action) { + next(e -> { + action.accept(e); + return true; + }); + } + + @Override + public double[] toArray() { + int estimatedSize = estimateSize(); + if (estimatedSize < 0) { + List list = new ArrayList<>(); + next(list::add); + double[] array = new double[list.size()]; + for (int i = 0; i < array.length; ++i) { + array[i] = list.get(i); + } + return array; + } else { + double[] array = new double[estimatedSize]; + ArrayFillingConsumer consumer = new ArrayFillingConsumer(array); + boolean wantsMore = next(consumer); + assert !wantsMore : "next() should have reported done status"; + if (consumer.index < array.length) { + array = Arrays.copyOf(array, consumer.index); + } + return array; + } + } + + @Override + public double reduce(double identity, DoubleBinaryOperator accumulator) { + TReducingDoubleConsumer consumer = new TReducingDoubleConsumer(accumulator, identity, true); + boolean wantsMore = next(consumer); + assert !wantsMore : "next() should have returned true"; + return consumer.result; + } + + @Override + public OptionalDouble reduce(DoubleBinaryOperator accumulator) { + TReducingDoubleConsumer consumer = new TReducingDoubleConsumer(accumulator, 0, false); + boolean wantsMore = next(consumer); + assert !wantsMore : "next() should have returned true"; + return consumer.initialized ? OptionalDouble.of(consumer.result) : OptionalDouble.empty(); + } + + @Override + public R collect(Supplier supplier, ObjDoubleConsumer accumulator, BiConsumer combiner) { + R collection = supplier.get(); + next(e -> { + accumulator.accept(collection, e); + return true; + }); + return collection; + } + + @Override + public OptionalDouble min() { + return reduce(Math::min); + } + + @Override + public OptionalDouble max() { + return reduce(Math::max); + } + + @Override + public long count() { + TCountingDoubleConsumer consumer = new TCountingDoubleConsumer(); + next(consumer); + return consumer.count; + } + + @Override + public double sum() { + TSumDoubleConsumer consumer = new TSumDoubleConsumer(); + next(consumer); + return consumer.sum; + } + + @Override + public OptionalDouble average() { + TAverageDoubleConsumer consumer = new TAverageDoubleConsumer(); + next(consumer); + return consumer.count > 0 ? OptionalDouble.of(consumer.sum / consumer.count) : OptionalDouble.empty(); + } + + @Override + public boolean anyMatch(DoublePredicate predicate) { + return next(predicate.negate()); + } + + @Override + public boolean allMatch(DoublePredicate predicate) { + return !next(predicate); + } + + @Override + public boolean noneMatch(DoublePredicate predicate) { + return !anyMatch(predicate); + } + + @Override + public OptionalDouble findFirst() { + TFindFirstDoubleConsumer consumer = new TFindFirstDoubleConsumer(); + next(consumer); + return consumer.hasAny ? OptionalDouble.of(consumer.result) : OptionalDouble.empty(); + } + + @Override + public OptionalDouble findAny() { + return findFirst(); + } + + @Override + public PrimitiveIterator.OfDouble iterator() { + return new TSimpleDoubleStreamIterator(this); + } + + @Override + public Spliterator.OfDouble spliterator() { + return new TSimpleDoubleStreamSpliterator(this); + } + + @Override + public TStream boxed() { + return new TBoxedDoubleStream(this); + } + + @Override + public boolean isParallel() { + return false; + } + + @Override + public TDoubleStream sequential() { + return this; + } + + @Override + public TDoubleStream parallel() { + return this; + } + + @Override + public TDoubleStream unordered() { + return this; + } + + @Override + public TDoubleStream onClose(Runnable closeHandler) { + return new TCloseHandlingDoubleStream(this, closeHandler); + } + + @Override + public void close() throws Exception { + } + + protected int estimateSize() { + return -1; + } + + public abstract boolean next(DoublePredicate consumer); + + class ArrayFillingConsumer implements DoublePredicate { + double[] array; + int index; + + ArrayFillingConsumer(double[] array) { + this.array = array; + } + + @Override + public boolean test(double t) { + array[index++] = t; + return true; + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TSimpleDoubleStreamIterator.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TSimpleDoubleStreamIterator.java new file mode 100644 index 000000000..ea26850a9 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TSimpleDoubleStreamIterator.java @@ -0,0 +1,65 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.NoSuchElementException; +import java.util.PrimitiveIterator; + +public class TSimpleDoubleStreamIterator implements PrimitiveIterator.OfDouble { + private static final byte NEEDS_MORE = 0; + private static final byte HAS_DATA = 1; + private static final byte LAST_ELEMENT = 2; + private static final byte DONE = 3; + + private TSimpleDoubleStreamImpl stream; + private double lastElement; + private byte state; + + public TSimpleDoubleStreamIterator(TSimpleDoubleStreamImpl stream) { + this.stream = stream; + } + + @Override + public boolean hasNext() { + fetchIfNeeded(); + return state != DONE; + } + + @Override + public double nextDouble() { + fetchIfNeeded(); + if (state == DONE) { + throw new NoSuchElementException(); + } + double result = lastElement; + state = state == LAST_ELEMENT ? DONE : NEEDS_MORE; + return result; + } + + private void fetchIfNeeded() { + if (state != NEEDS_MORE) { + return; + } + boolean hasMore = stream.next(e -> { + lastElement = e; + return false; + }); + state = hasMore ? HAS_DATA : LAST_ELEMENT; + if (state == LAST_ELEMENT) { + stream = null; + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TSimpleDoubleStreamSpliterator.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TSimpleDoubleStreamSpliterator.java new file mode 100644 index 000000000..dbe2748ba --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TSimpleDoubleStreamSpliterator.java @@ -0,0 +1,63 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.Spliterator; +import java.util.function.DoubleConsumer; + +public class TSimpleDoubleStreamSpliterator implements Spliterator.OfDouble { + private TSimpleDoubleStreamImpl stream; + private boolean done; + + public TSimpleDoubleStreamSpliterator(TSimpleDoubleStreamImpl stream) { + this.stream = stream; + } + + @Override + public void forEachRemaining(DoubleConsumer action) { + stream.next(x -> { + action.accept(x); + return true; + }); + } + + @Override + public boolean tryAdvance(DoubleConsumer action) { + if (done) { + return false; + } + done = !stream.next(x -> { + action.accept(x); + return false; + }); + return true; + } + + @Override + public OfDouble trySplit() { + return null; + } + + @Override + public long estimateSize() { + return stream.estimateSize(); + } + + @Override + public int characteristics() { + return 0; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TSingleDoubleStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TSingleDoubleStreamImpl.java new file mode 100644 index 000000000..3a5f32be3 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TSingleDoubleStreamImpl.java @@ -0,0 +1,42 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.function.DoublePredicate; + +public class TSingleDoubleStreamImpl extends TSimpleDoubleStreamImpl { + private double element; + + public TSingleDoubleStreamImpl(double element) { + this.element = element; + } + + @Override + public boolean next(DoublePredicate consumer) { + consumer.test(element); + return false; + } + + @Override + protected int estimateSize() { + return 1; + } + + @Override + public long count() { + return 1; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TSkippingDoubleStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TSkippingDoubleStreamImpl.java new file mode 100644 index 000000000..75e0a4267 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TSkippingDoubleStreamImpl.java @@ -0,0 +1,51 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.function.DoublePredicate; + +public class TSkippingDoubleStreamImpl extends TSimpleDoubleStreamImpl { + private TSimpleDoubleStreamImpl sourceStream; + private int skip; + private int remaining; + + public TSkippingDoubleStreamImpl(TSimpleDoubleStreamImpl sourceStream, int skip) { + this.sourceStream = sourceStream; + this.skip = skip; + remaining = skip; + } + + @Override + public boolean next(DoublePredicate consumer) { + if (remaining > 0) { + if (!sourceStream.next(e -> --remaining > 0)) { + return false; + } + } + return sourceStream.next(consumer); + } + + @Override + protected int estimateSize() { + int sourceSize = sourceStream.estimateSize(); + return sourceSize >= 0 ? Math.max(0, sourceSize - skip) : -1; + } + + @Override + public void close() throws Exception { + sourceStream.close(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TSpecializedConcatDoubleStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TSpecializedConcatDoubleStream.java new file mode 100644 index 000000000..38ac89ed2 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TSpecializedConcatDoubleStream.java @@ -0,0 +1,78 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.function.DoublePredicate; + +public class TSpecializedConcatDoubleStream extends TSimpleDoubleStreamImpl { + TSimpleDoubleStreamImpl first; + TSimpleDoubleStreamImpl second; + TSimpleDoubleStreamImpl current; + + public TSpecializedConcatDoubleStream(TSimpleDoubleStreamImpl first, TSimpleDoubleStreamImpl second) { + this.first = first; + this.second = second; + current = first; + } + + @Override + public boolean next(DoublePredicate consumer) { + if (current == null) { + return false; + } + while (true) { + if (current.next(consumer)) { + return true; + } + if (current == first) { + current = second; + } else { + current = null; + return false; + } + } + } + + @Override + protected int estimateSize() { + int firstSize = first.estimateSize(); + int secondSize = second.estimateSize(); + return firstSize >= 0 && secondSize >= 0 ? firstSize + secondSize : -1; + } + + @Override + public long count() { + return first.count() + second.count(); + } + + @Override + public void close() throws Exception { + RuntimeException suppressed = null; + try { + first.close(); + } catch (RuntimeException e) { + suppressed = e; + } + try { + second.close(); + } catch (RuntimeException e) { + if (suppressed != null) { + e.addSuppressed(suppressed); + } + throw e; + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TSumDoubleConsumer.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TSumDoubleConsumer.java new file mode 100644 index 000000000..abdda307c --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TSumDoubleConsumer.java @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.function.DoublePredicate; + +public class TSumDoubleConsumer implements DoublePredicate { + double sum; + + @Override + public boolean test(double t) { + sum += t; + return true; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TWrappingDoubleStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TWrappingDoubleStreamImpl.java new file mode 100644 index 000000000..0e56f03a7 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/doubleimpl/TWrappingDoubleStreamImpl.java @@ -0,0 +1,43 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.doubleimpl; + +import java.util.function.DoublePredicate; + +public abstract class TWrappingDoubleStreamImpl extends TSimpleDoubleStreamImpl { + TSimpleDoubleStreamImpl sourceStream; + + public TWrappingDoubleStreamImpl(TSimpleDoubleStreamImpl sourceStream) { + this.sourceStream = sourceStream; + } + + @Override + public boolean next(DoublePredicate consumer) { + return sourceStream.next(wrap(consumer)); + } + + protected abstract DoublePredicate wrap(DoublePredicate consumer); + + @Override + protected int estimateSize() { + return sourceStream.estimateSize(); + } + + @Override + public void close() throws Exception { + sourceStream.close(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TArrayStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TArrayStreamImpl.java new file mode 100644 index 000000000..7432bb3aa --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TArrayStreamImpl.java @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.function.Predicate; + +public class TArrayStreamImpl extends TSimpleStreamImpl { + private T[] array; + private int index; + private int end; + private int size; + + public TArrayStreamImpl(T[] array, int start, int end) { + this.array = array; + index = start; + this.end = end; + size = end - start; + } + + @Override + public boolean next(Predicate consumer) { + while (index < end) { + if (!consumer.test(array[index++])) { + break; + } + } + return index < end; + } + + @Override + protected int estimateSize() { + return size; + } + + @Override + public long count() { + return size; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TCloseHandlingStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TCloseHandlingStream.java new file mode 100644 index 000000000..ed13aa8d5 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TCloseHandlingStream.java @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.function.Predicate; + +public class TCloseHandlingStream extends TSimpleStreamImpl { + private TSimpleStreamImpl innerStream; + private Runnable closeHandler; + + public TCloseHandlingStream(TSimpleStreamImpl innerStream, Runnable closeHandler) { + this.innerStream = innerStream; + this.closeHandler = closeHandler; + } + + @Override + public boolean next(Predicate consumer) { + return innerStream.next(consumer); + } + + @Override + public void close() throws Exception { + RuntimeException previousException = null; + try { + closeHandler.run(); + } catch (RuntimeException e) { + previousException = e; + } + + try { + innerStream.close(); + } catch (RuntimeException e) { + if (previousException != null) { + e.addSuppressed(previousException); + } + throw e; + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TCountingConsumer.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TCountingConsumer.java new file mode 100644 index 000000000..b0a082432 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TCountingConsumer.java @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.function.Predicate; + +public class TCountingConsumer implements Predicate { + int count; + + @Override + public boolean test(T t) { + count++; + return true; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TDistinctStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TDistinctStreamImpl.java new file mode 100644 index 000000000..022751038 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TDistinctStreamImpl.java @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.HashSet; +import java.util.Set; +import java.util.function.Predicate; + +public class TDistinctStreamImpl extends TWrappingStreamImpl { + public TDistinctStreamImpl(TSimpleStreamImpl innerStream) { + super(innerStream); + } + + @Override + protected Predicate wrap(Predicate consumer) { + Set visited = new HashSet<>(); + return e -> { + if (!visited.add(e)) { + return true; + } + return consumer.test(e); + }; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TEmptyStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TEmptyStreamImpl.java new file mode 100644 index 000000000..563b5d35d --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TEmptyStreamImpl.java @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.function.Predicate; + +public class TEmptyStreamImpl extends TSimpleStreamImpl { + @Override + public boolean next(Predicate consumer) { + return false; + } + + @Override + protected int estimateSize() { + return 0; + } + + @Override + public long count() { + return 1; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TFilteringStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TFilteringStreamImpl.java new file mode 100644 index 000000000..1e9657da8 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TFilteringStreamImpl.java @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.function.Predicate; + +public class TFilteringStreamImpl extends TWrappingStreamImpl { + private Predicate filter; + + public TFilteringStreamImpl(TSimpleStreamImpl innerStream, Predicate filter) { + super(innerStream); + this.filter = filter; + } + + @Override + protected Predicate wrap(Predicate consumer) { + return t -> { + if (!filter.test(t)) { + return true; + } + return consumer.test(t); + }; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TFindFirstConsumer.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TFindFirstConsumer.java new file mode 100644 index 000000000..26ccbeb99 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TFindFirstConsumer.java @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.function.Predicate; + +public class TFindFirstConsumer implements Predicate { + public T result; + + @Override + public boolean test(T t) { + result = t; + return false; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TFlatMappingStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TFlatMappingStreamImpl.java new file mode 100644 index 000000000..953be0db0 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TFlatMappingStreamImpl.java @@ -0,0 +1,82 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.Iterator; +import java.util.function.Function; +import java.util.function.Predicate; +import org.teavm.classlib.java.util.stream.TStream; + +public class TFlatMappingStreamImpl extends TSimpleStreamImpl { + private TSimpleStreamImpl sourceStream; + private TStream current; + private Iterator iterator; + private Function> mapper; + private boolean done; + + public TFlatMappingStreamImpl(TSimpleStreamImpl sourceStream, + Function> mapper) { + this.sourceStream = sourceStream; + this.mapper = mapper; + } + + @Override + public boolean next(Predicate consumer) { + while (true) { + if (current == null) { + if (done) { + return false; + } + boolean hasMore = sourceStream.next(e -> { + current = mapper.apply(e); + return false; + }); + if (!hasMore) { + done = true; + } + if (current == null) { + done = true; + return false; + } + } + if (current instanceof TSimpleStreamImpl) { + @SuppressWarnings("unchecked") + TSimpleStreamImpl castCurrent = (TSimpleStreamImpl) current; + if (castCurrent.next(consumer)) { + return true; + } + current = null; + } else { + iterator = current.iterator(); + while (iterator.hasNext()) { + T e = iterator.next(); + if (!consumer.test(e)) { + return true; + } + } + iterator = null; + current = null; + } + } + } + + @Override + public void close() throws Exception { + current = null; + iterator = null; + sourceStream.close(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TFlatMappingToDoubleStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TFlatMappingToDoubleStreamImpl.java new file mode 100644 index 000000000..f32fb25bb --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TFlatMappingToDoubleStreamImpl.java @@ -0,0 +1,83 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.PrimitiveIterator; +import java.util.function.DoublePredicate; +import java.util.function.Function; +import org.teavm.classlib.java.util.stream.TDoubleStream; +import org.teavm.classlib.java.util.stream.doubleimpl.TSimpleDoubleStreamImpl; + +public class TFlatMappingToDoubleStreamImpl extends TSimpleDoubleStreamImpl { + private TSimpleStreamImpl sourceStream; + private TDoubleStream current; + private PrimitiveIterator.OfDouble iterator; + private Function mapper; + private boolean done; + + public TFlatMappingToDoubleStreamImpl(TSimpleStreamImpl sourceStream, + Function mapper) { + this.sourceStream = sourceStream; + this.mapper = mapper; + } + + @Override + public boolean next(DoublePredicate consumer) { + while (true) { + if (current == null) { + if (done) { + return false; + } + boolean hasMore = sourceStream.next(e -> { + current = mapper.apply(e); + return false; + }); + if (!hasMore) { + done = true; + } + if (current == null) { + done = true; + return false; + } + } + if (current instanceof TSimpleDoubleStreamImpl) { + @SuppressWarnings("unchecked") + TSimpleDoubleStreamImpl castCurrent = (TSimpleDoubleStreamImpl) current; + if (castCurrent.next(consumer)) { + return true; + } + current = null; + } else { + iterator = current.iterator(); + while (iterator.hasNext()) { + double e = iterator.nextDouble(); + if (!consumer.test(e)) { + return true; + } + } + iterator = null; + current = null; + } + } + } + + @Override + public void close() throws Exception { + current = null; + iterator = null; + sourceStream.close(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TFlatMappingToIntStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TFlatMappingToIntStreamImpl.java new file mode 100644 index 000000000..423b6cdde --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TFlatMappingToIntStreamImpl.java @@ -0,0 +1,83 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.PrimitiveIterator; +import java.util.function.Function; +import java.util.function.IntPredicate; +import org.teavm.classlib.java.util.stream.TIntStream; +import org.teavm.classlib.java.util.stream.intimpl.TSimpleIntStreamImpl; + +public class TFlatMappingToIntStreamImpl extends TSimpleIntStreamImpl { + private TSimpleStreamImpl sourceStream; + private TIntStream current; + private PrimitiveIterator.OfInt iterator; + private Function mapper; + private boolean done; + + public TFlatMappingToIntStreamImpl(TSimpleStreamImpl sourceStream, + Function mapper) { + this.sourceStream = sourceStream; + this.mapper = mapper; + } + + @Override + public boolean next(IntPredicate consumer) { + while (true) { + if (current == null) { + if (done) { + return false; + } + boolean hasMore = sourceStream.next(e -> { + current = mapper.apply(e); + return false; + }); + if (!hasMore) { + done = true; + } + if (current == null) { + done = true; + return false; + } + } + if (current instanceof TSimpleIntStreamImpl) { + @SuppressWarnings("unchecked") + TSimpleIntStreamImpl castCurrent = (TSimpleIntStreamImpl) current; + if (castCurrent.next(consumer)) { + return true; + } + current = null; + } else { + iterator = current.iterator(); + while (iterator.hasNext()) { + int e = iterator.nextInt(); + if (!consumer.test(e)) { + return true; + } + } + iterator = null; + current = null; + } + } + } + + @Override + public void close() throws Exception { + current = null; + iterator = null; + sourceStream.close(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TFlatMappingToLongStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TFlatMappingToLongStreamImpl.java new file mode 100644 index 000000000..9183fa208 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TFlatMappingToLongStreamImpl.java @@ -0,0 +1,83 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.PrimitiveIterator; +import java.util.function.Function; +import java.util.function.LongPredicate; +import org.teavm.classlib.java.util.stream.TLongStream; +import org.teavm.classlib.java.util.stream.longimpl.TSimpleLongStreamImpl; + +public class TFlatMappingToLongStreamImpl extends TSimpleLongStreamImpl { + private TSimpleStreamImpl sourceStream; + private TLongStream current; + private PrimitiveIterator.OfLong iterator; + private Function mapper; + private boolean done; + + public TFlatMappingToLongStreamImpl(TSimpleStreamImpl sourceStream, + Function mapper) { + this.sourceStream = sourceStream; + this.mapper = mapper; + } + + @Override + public boolean next(LongPredicate consumer) { + while (true) { + if (current == null) { + if (done) { + return false; + } + boolean hasMore = sourceStream.next(e -> { + current = mapper.apply(e); + return false; + }); + if (!hasMore) { + done = true; + } + if (current == null) { + done = true; + return false; + } + } + if (current instanceof TSimpleLongStreamImpl) { + @SuppressWarnings("unchecked") + TSimpleLongStreamImpl castCurrent = (TSimpleLongStreamImpl) current; + if (castCurrent.next(consumer)) { + return true; + } + current = null; + } else { + iterator = current.iterator(); + while (iterator.hasNext()) { + long e = iterator.nextLong(); + if (!consumer.test(e)) { + return true; + } + } + iterator = null; + current = null; + } + } + } + + @Override + public void close() throws Exception { + current = null; + iterator = null; + sourceStream.close(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TGenerateStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TGenerateStream.java new file mode 100644 index 000000000..8e016f0b6 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TGenerateStream.java @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.function.Predicate; +import java.util.function.Supplier; + +public class TGenerateStream extends TSimpleStreamImpl { + private Supplier s; + + public TGenerateStream(Supplier s) { + this.s = s; + } + + @Override + public boolean next(Predicate consumer) { + while (consumer.test(s.get())) { + // go on + } + return true; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TGenericConcatStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TGenericConcatStream.java new file mode 100644 index 000000000..a39e5c466 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TGenericConcatStream.java @@ -0,0 +1,75 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.Iterator; +import java.util.function.Predicate; +import org.teavm.classlib.java.util.stream.TStream; + +public class TGenericConcatStream extends TSimpleStreamImpl { + TStream first; + TStream second; + Iterator iterator; + boolean isSecond; + + public TGenericConcatStream(TStream first, TStream second) { + this.first = first; + this.second = second; + } + + @Override + public boolean next(Predicate consumer) { + if (iterator == null) { + iterator = first.iterator(); + } + while (true) { + while (iterator.hasNext()) { + if (!consumer.test(iterator.next())) { + return true; + } + } + if (!isSecond) { + isSecond = true; + iterator = second.iterator(); + } else { + return false; + } + } + } + + @Override + public long count() { + return first.count() + second.count(); + } + + @Override + public void close() throws Exception { + Exception suppressed = null; + try { + first.close(); + } catch (Exception e) { + suppressed = e; + } + try { + second.close(); + } catch (Exception e) { + if (suppressed != null) { + e.addSuppressed(suppressed); + } + throw e; + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TIterateStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TIterateStream.java new file mode 100644 index 000000000..1522cef78 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TIterateStream.java @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.function.Predicate; +import java.util.function.UnaryOperator; + +public class TIterateStream extends TSimpleStreamImpl { + private T value; + private UnaryOperator f; + + public TIterateStream(T value, UnaryOperator f) { + this.value = value; + this.f = f; + } + + @Override + public boolean next(Predicate consumer) { + while (true) { + T valueToReport = value; + value = f.apply(value); + if (!consumer.test(valueToReport)) { + return true; + } + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TLimitingStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TLimitingStreamImpl.java new file mode 100644 index 000000000..c66ec4239 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TLimitingStreamImpl.java @@ -0,0 +1,58 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.function.Predicate; + +public class TLimitingStreamImpl extends TSimpleStreamImpl { + private TSimpleStreamImpl sourceStream; + private int limit; + private int remaining; + + public TLimitingStreamImpl(TSimpleStreamImpl sourceStream, int limit) { + this.sourceStream = sourceStream; + this.limit = limit; + remaining = limit; + } + + @Override + public boolean next(Predicate consumer) { + if (remaining == 0) { + return false; + } + boolean result = sourceStream.next(e -> { + if (remaining-- == 0) { + return false; + } + return consumer.test(e); + }); + if (!result) { + remaining = 0; + } + return remaining > 0; + } + + @Override + protected int estimateSize() { + int sourceEstimation = sourceStream.estimateSize(); + return sourceEstimation < 0 ? limit : Math.min(limit, sourceEstimation); + } + + @Override + public void close() throws Exception { + sourceStream.close(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TMappingStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TMappingStreamImpl.java new file mode 100644 index 000000000..955b4b22a --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TMappingStreamImpl.java @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.function.Function; +import java.util.function.Predicate; + +public class TMappingStreamImpl extends TWrappingStreamImpl { + private Function mapper; + + public TMappingStreamImpl(TSimpleStreamImpl sourceStream, Function mapper) { + super(sourceStream); + this.mapper = mapper; + } + + @Override + protected Predicate wrap(Predicate consumer) { + return t -> consumer.test(mapper.apply(t)); + } + + @Override + public long count() { + return sourceStream.count(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TMappingToDoubleStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TMappingToDoubleStreamImpl.java new file mode 100644 index 000000000..d8a138049 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TMappingToDoubleStreamImpl.java @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.function.DoublePredicate; +import java.util.function.ToDoubleFunction; +import org.teavm.classlib.java.util.stream.doubleimpl.TSimpleDoubleStreamImpl; + +public class TMappingToDoubleStreamImpl extends TSimpleDoubleStreamImpl { + private TSimpleStreamImpl source; + private ToDoubleFunction mapper; + + public TMappingToDoubleStreamImpl(TSimpleStreamImpl source, ToDoubleFunction mapper) { + this.source = source; + this.mapper = mapper; + } + + @Override + public boolean next(DoublePredicate consumer) { + return source.next(e -> consumer.test(mapper.applyAsDouble(e))); + } + + @Override + public void close() throws Exception { + source.close(); + } + + @Override + protected int estimateSize() { + return source.estimateSize(); + } + + @Override + public long count() { + return source.count(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TMappingToIntStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TMappingToIntStreamImpl.java new file mode 100644 index 000000000..a4e6006e4 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TMappingToIntStreamImpl.java @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.function.IntPredicate; +import java.util.function.ToIntFunction; +import org.teavm.classlib.java.util.stream.intimpl.TSimpleIntStreamImpl; + +public class TMappingToIntStreamImpl extends TSimpleIntStreamImpl { + private TSimpleStreamImpl source; + private ToIntFunction mapper; + + public TMappingToIntStreamImpl(TSimpleStreamImpl source, ToIntFunction mapper) { + this.source = source; + this.mapper = mapper; + } + + @Override + public boolean next(IntPredicate consumer) { + return source.next(e -> consumer.test(mapper.applyAsInt(e))); + } + + @Override + public void close() throws Exception { + source.close(); + } + + @Override + protected int estimateSize() { + return source.estimateSize(); + } + + @Override + public long count() { + return source.count(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TMappingToLongStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TMappingToLongStreamImpl.java new file mode 100644 index 000000000..4acb9840f --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TMappingToLongStreamImpl.java @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.function.LongPredicate; +import java.util.function.ToLongFunction; +import org.teavm.classlib.java.util.stream.longimpl.TSimpleLongStreamImpl; + +public class TMappingToLongStreamImpl extends TSimpleLongStreamImpl { + private TSimpleStreamImpl source; + private ToLongFunction mapper; + + public TMappingToLongStreamImpl(TSimpleStreamImpl source, ToLongFunction mapper) { + this.source = source; + this.mapper = mapper; + } + + @Override + public boolean next(LongPredicate consumer) { + return source.next(e -> consumer.test(mapper.applyAsLong(e))); + } + + @Override + public void close() throws Exception { + source.close(); + } + + @Override + protected int estimateSize() { + return source.estimateSize(); + } + + @Override + public long count() { + return source.count(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TPeekingStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TPeekingStreamImpl.java new file mode 100644 index 000000000..7f68ad9f3 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TPeekingStreamImpl.java @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.function.Consumer; +import java.util.function.Predicate; + +public class TPeekingStreamImpl extends TWrappingStreamImpl { + private Consumer elementConsumer; + + public TPeekingStreamImpl(TSimpleStreamImpl sourceStream, Consumer elementConsumer) { + super(sourceStream); + this.elementConsumer = elementConsumer; + } + + @Override + protected Predicate wrap(Predicate consumer) { + return e -> { + elementConsumer.accept(e); + return consumer.test(e); + }; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TReducingConsumer.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TReducingConsumer.java new file mode 100644 index 000000000..d79be3f62 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TReducingConsumer.java @@ -0,0 +1,42 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.function.BinaryOperator; +import java.util.function.Predicate; + +class TReducingConsumer implements Predicate { + private BinaryOperator accumulator; + T result; + boolean initialized; + + TReducingConsumer(BinaryOperator accumulator, T result, boolean initialized) { + this.accumulator = accumulator; + this.result = result; + this.initialized = initialized; + } + + @Override + public boolean test(T t) { + if (!initialized) { + result = t; + initialized = true; + } else { + result = accumulator.apply(result, t); + } + return true; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TReducingConsumer2.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TReducingConsumer2.java new file mode 100644 index 000000000..14dd45956 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TReducingConsumer2.java @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.function.BiFunction; +import java.util.function.Predicate; + +class TReducingConsumer2 implements Predicate { + private BiFunction accumulator; + U result; + + TReducingConsumer2(BiFunction accumulator, U result) { + this.accumulator = accumulator; + this.result = result; + } + + @Override + public boolean test(T t) { + result = accumulator.apply(result, t); + return true; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TSimpleStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TSimpleStreamImpl.java new file mode 100644 index 000000000..ff37e066a --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TSimpleStreamImpl.java @@ -0,0 +1,310 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; +import java.util.Spliterator; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.BinaryOperator; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.IntFunction; +import java.util.function.Predicate; +import java.util.function.Supplier; +import java.util.function.ToDoubleFunction; +import java.util.function.ToIntFunction; +import java.util.function.ToLongFunction; +import org.teavm.classlib.java.util.stream.TCollector; +import org.teavm.classlib.java.util.stream.TDoubleStream; +import org.teavm.classlib.java.util.stream.TIntStream; +import org.teavm.classlib.java.util.stream.TLongStream; +import org.teavm.classlib.java.util.stream.TStream; + +public abstract class TSimpleStreamImpl implements TStream { + @Override + public TStream filter(Predicate predicate) { + return new TFilteringStreamImpl<>(this, predicate); + } + + @Override + public TStream map(Function mapper) { + return new TMappingStreamImpl<>(this, mapper); + } + + @Override + public TIntStream mapToInt(ToIntFunction mapper) { + return new TMappingToIntStreamImpl<>(this, mapper); + } + + @Override + public TLongStream mapToLong(ToLongFunction mapper) { + return new TMappingToLongStreamImpl<>(this, mapper); + } + + @Override + public TDoubleStream mapToDouble(ToDoubleFunction mapper) { + return new TMappingToDoubleStreamImpl<>(this, mapper); + } + + @Override + public TStream flatMap(Function> mapper) { + return new TFlatMappingStreamImpl<>(this, mapper); + } + + @Override + public TIntStream flatMapToInt(Function mapper) { + return new TFlatMappingToIntStreamImpl<>(this, mapper); + } + + @Override + public TLongStream flatMapToLong(Function mapper) { + return new TFlatMappingToLongStreamImpl<>(this, mapper); + } + + @Override + public TDoubleStream flatMapToDouble(Function mapper) { + return new TFlatMappingToDoubleStreamImpl<>(this, mapper); + } + + @Override + public TStream distinct() { + return new TDistinctStreamImpl<>(this); + } + + @Override + @SuppressWarnings("unchecked") + public TStream sorted() { + return new TSortedStreamImpl<>(this, (a, b) -> ((Comparable) a).compareTo(b)); + } + + @Override + public TStream sorted(Comparator comparator) { + return new TSortedStreamImpl<>(this, comparator); + } + + @Override + public TStream peek(Consumer action) { + return new TPeekingStreamImpl<>(this, action); + } + + @Override + public TStream limit(long maxSize) { + return new TLimitingStreamImpl<>(this, (int) maxSize); + } + + @Override + public TStream skip(long n) { + return new TSkippingStreamImpl<>(this, (int) n); + } + + @Override + public void forEach(Consumer action) { + forEachOrdered(action); + } + + @Override + public void forEachOrdered(Consumer action) { + next(e -> { + action.accept(e); + return true; + }); + } + + @Override + public Object[] toArray() { + return toArray(Object[]::new); + } + + @Override + @SuppressWarnings("unchecked") + public A[] toArray(IntFunction generator) { + int estimatedSize = estimateSize(); + if (estimatedSize < 0) { + List list = new ArrayList<>(); + next(list::add); + A[] array = generator.apply(list.size()); + for (int i = 0; i < array.length; ++i) { + array[i] = (A) list.get(i); + } + return array; + } else { + A[] array = generator.apply(estimatedSize); + ArrayFillingConsumer consumer = new ArrayFillingConsumer<>(array); + boolean wantsMore = next(consumer); + assert !wantsMore : "next() should have reported done status"; + if (consumer.index < array.length) { + array = Arrays.copyOf(array, consumer.index); + } + return array; + } + } + + @Override + public T reduce(T identity, BinaryOperator accumulator) { + TReducingConsumer consumer = new TReducingConsumer<>(accumulator, identity, true); + boolean wantsMore = next(consumer); + assert !wantsMore : "next() should have returned true"; + return consumer.result; + } + + @Override + public Optional reduce(BinaryOperator accumulator) { + TReducingConsumer consumer = new TReducingConsumer<>(accumulator, null, false); + boolean wantsMore = next(consumer); + assert !wantsMore : "next() should have returned true"; + return Optional.ofNullable(consumer.result); + } + + @Override + public U reduce(U identity, BiFunction accumulator, BinaryOperator combiner) { + TReducingConsumer2 consumer = new TReducingConsumer2<>(accumulator, identity); + boolean wantsMore = next(consumer); + assert !wantsMore : "next() should have returned true"; + return consumer.result; + } + + @Override + public R collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner) { + R collection = supplier.get(); + next(e -> { + accumulator.accept(collection, e); + return true; + }); + return collection; + } + + @Override + public R collect(TCollector collector) { + A collection = collector.supplier().get(); + BiConsumer accumulator = collector.accumulator(); + next(e -> { + accumulator.accept(collection, e); + return true; + }); + return collector.finisher().apply(collection); + } + + @Override + public Optional min(Comparator comparator) { + return reduce((a, b) -> comparator.compare(a, b) < 0 ? a : b); + } + + @Override + public Optional max(Comparator comparator) { + return reduce((a, b) -> comparator.compare(a, b) > 0 ? a : b); + } + + @Override + public long count() { + TCountingConsumer consumer = new TCountingConsumer<>(); + next(consumer); + return consumer.count; + } + + @Override + public boolean anyMatch(Predicate predicate) { + return next(predicate.negate()); + } + + @Override + public boolean allMatch(Predicate predicate) { + return !next(predicate); + } + + @Override + public boolean noneMatch(Predicate predicate) { + return !anyMatch(predicate); + } + + @Override + public Optional findFirst() { + TFindFirstConsumer consumer = new TFindFirstConsumer<>(); + next(consumer); + return Optional.ofNullable(consumer.result); + } + + @Override + public Optional findAny() { + return findFirst(); + } + + @Override + public Iterator iterator() { + return new TSimpleStreamIterator<>(this); + } + + @Override + public Spliterator spliterator() { + return new TSimpleStreamSpliterator<>(this); + } + + @Override + public boolean isParallel() { + return false; + } + + @Override + public TStream sequential() { + return this; + } + + @Override + public TStream parallel() { + return this; + } + + @Override + public TStream unordered() { + return this; + } + + @Override + public TStream onClose(Runnable closeHandler) { + return new TCloseHandlingStream<>(this, closeHandler); + } + + @Override + public void close() throws Exception { + } + + protected int estimateSize() { + return -1; + } + + public abstract boolean next(Predicate consumer); + + class ArrayFillingConsumer implements Predicate { + A[] array; + int index; + + ArrayFillingConsumer(A[] array) { + this.array = array; + } + + @Override + @SuppressWarnings("unchecked") + public boolean test(T t) { + array[index++] = (A) t; + return true; + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TSimpleStreamIterator.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TSimpleStreamIterator.java new file mode 100644 index 000000000..6b4659802 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TSimpleStreamIterator.java @@ -0,0 +1,75 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.function.Consumer; + +public class TSimpleStreamIterator implements Iterator { + private static final byte NEEDS_MORE = 0; + private static final byte HAS_DATA = 1; + private static final byte LAST_ELEMENT = 2; + private static final byte DONE = 3; + + private TSimpleStreamImpl stream; + private T lastElement; + private byte state; + + public TSimpleStreamIterator(TSimpleStreamImpl stream) { + this.stream = stream; + } + + @Override + public void forEachRemaining(Consumer action) { + stream.next(x -> { + action.accept(x); + return true; + }); + } + + @Override + public boolean hasNext() { + fetchIfNeeded(); + return state != DONE; + } + + @Override + public T next() { + fetchIfNeeded(); + if (state == DONE) { + throw new NoSuchElementException(); + } + T result = lastElement; + lastElement = null; + state = state == LAST_ELEMENT ? DONE : NEEDS_MORE; + return result; + } + + private void fetchIfNeeded() { + if (state != NEEDS_MORE) { + return; + } + boolean hasMore = stream.next(e -> { + lastElement = e; + return false; + }); + state = hasMore ? HAS_DATA : LAST_ELEMENT; + if (state == LAST_ELEMENT) { + stream = null; + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TSimpleStreamSpliterator.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TSimpleStreamSpliterator.java new file mode 100644 index 000000000..45a0cdee5 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TSimpleStreamSpliterator.java @@ -0,0 +1,63 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.Spliterator; +import java.util.function.Consumer; + +public class TSimpleStreamSpliterator implements Spliterator { + private TSimpleStreamImpl stream; + private boolean done; + + public TSimpleStreamSpliterator(TSimpleStreamImpl stream) { + this.stream = stream; + } + + @Override + public void forEachRemaining(Consumer action) { + stream.next(x -> { + action.accept(x); + return true; + }); + } + + @Override + public boolean tryAdvance(Consumer action) { + if (done) { + return false; + } + done = !stream.next(x -> { + action.accept(x); + return false; + }); + return true; + } + + @Override + public Spliterator trySplit() { + return null; + } + + @Override + public long estimateSize() { + return stream.estimateSize(); + } + + @Override + public int characteristics() { + return 0; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TSingleStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TSingleStreamImpl.java new file mode 100644 index 000000000..9928ca783 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TSingleStreamImpl.java @@ -0,0 +1,42 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.function.Predicate; + +public class TSingleStreamImpl extends TSimpleStreamImpl { + private T element; + + public TSingleStreamImpl(T element) { + this.element = element; + } + + @Override + public boolean next(Predicate consumer) { + consumer.test(element); + return false; + } + + @Override + protected int estimateSize() { + return 1; + } + + @Override + public long count() { + return 1; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TSkippingStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TSkippingStreamImpl.java new file mode 100644 index 000000000..20c6b944d --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TSkippingStreamImpl.java @@ -0,0 +1,51 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.function.Predicate; + +public class TSkippingStreamImpl extends TSimpleStreamImpl { + private TSimpleStreamImpl sourceStream; + private int skip; + private int remaining; + + public TSkippingStreamImpl(TSimpleStreamImpl sourceStream, int skip) { + this.sourceStream = sourceStream; + this.skip = skip; + remaining = skip; + } + + @Override + public boolean next(Predicate consumer) { + if (remaining > 0) { + if (!sourceStream.next(e -> --remaining > 0)) { + return false; + } + } + return sourceStream.next(consumer); + } + + @Override + protected int estimateSize() { + int sourceSize = sourceStream.estimateSize(); + return sourceSize >= 0 ? Math.max(0, sourceSize - skip) : -1; + } + + @Override + public void close() throws Exception { + sourceStream.close(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TSortedStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TSortedStreamImpl.java new file mode 100644 index 000000000..07ef35b33 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TSortedStreamImpl.java @@ -0,0 +1,53 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.function.Predicate; + +public class TSortedStreamImpl extends TSimpleStreamImpl { + private TSimpleStreamImpl sourceStream; + private T[] array; + private int index; + + @SuppressWarnings("unchecked") + public TSortedStreamImpl(TSimpleStreamImpl sourceStream, Comparator comparator) { + this.sourceStream = sourceStream; + array = (T[]) sourceStream.toArray(Object[]::new); + Arrays.sort(array, comparator); + } + + @Override + public boolean next(Predicate consumer) { + while (index < array.length) { + if (!consumer.test(array[index++])) { + break; + } + } + return index < array.length; + } + + @Override + protected int estimateSize() { + return sourceStream.estimateSize(); + } + + @Override + public void close() throws Exception { + sourceStream.close(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TSpecializedConcatStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TSpecializedConcatStream.java new file mode 100644 index 000000000..5b9e3ded4 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TSpecializedConcatStream.java @@ -0,0 +1,78 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.function.Predicate; + +public class TSpecializedConcatStream extends TSimpleStreamImpl { + TSimpleStreamImpl first; + TSimpleStreamImpl second; + TSimpleStreamImpl current; + + public TSpecializedConcatStream(TSimpleStreamImpl first, TSimpleStreamImpl second) { + this.first = first; + this.second = second; + current = first; + } + + @Override + public boolean next(Predicate consumer) { + if (current == null) { + return false; + } + while (true) { + if (current.next(consumer)) { + return true; + } + if (current == first) { + current = second; + } else { + current = null; + return false; + } + } + } + + @Override + protected int estimateSize() { + int firstSize = first.estimateSize(); + int secondSize = second.estimateSize(); + return firstSize >= 0 && secondSize >= 0 ? firstSize + secondSize : -1; + } + + @Override + public long count() { + return first.count() + second.count(); + } + + @Override + public void close() throws Exception { + RuntimeException suppressed = null; + try { + first.close(); + } catch (RuntimeException e) { + suppressed = e; + } + try { + second.close(); + } catch (RuntimeException e) { + if (suppressed != null) { + e.addSuppressed(suppressed); + } + throw e; + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TSpliteratorOverCollection.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TSpliteratorOverCollection.java new file mode 100644 index 000000000..05aca4f0b --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TSpliteratorOverCollection.java @@ -0,0 +1,70 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.function.Consumer; +import org.teavm.classlib.java.util.TCollection; +import org.teavm.classlib.java.util.TIterator; +import org.teavm.classlib.java.util.TSpliterator; + +public class TSpliteratorOverCollection implements TSpliterator { + private TCollection collection; + private TIterator iterator; + + public TSpliteratorOverCollection(TCollection collection) { + this.collection = collection; + } + + @Override + public boolean tryAdvance(Consumer action) { + ensureIterator(); + if (iterator.hasNext()) { + action.accept(iterator.next()); + return true; + } else { + return false; + } + } + + @Override + public void forEachRemaining(Consumer action) { + ensureIterator(); + while (iterator.hasNext()) { + action.accept(iterator.next()); + } + } + + private void ensureIterator() { + if (iterator == null) { + iterator = collection.iterator(); + } + } + + @Override + public TSpliterator trySplit() { + return null; + } + + @Override + public long estimateSize() { + return collection.size(); + } + + @Override + public int characteristics() { + return TSpliterator.SIZED; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TStreamBuilder.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TStreamBuilder.java new file mode 100644 index 000000000..91d796e51 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TStreamBuilder.java @@ -0,0 +1,34 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import org.teavm.classlib.java.util.TArrayList; +import org.teavm.classlib.java.util.TList; +import org.teavm.classlib.java.util.stream.TStream; + +public class TStreamBuilder implements TStream.Builder { + private TList elements = new TArrayList<>(); + + @Override + public void accept(T t) { + elements.add(t); + } + + @Override + public TStream build() { + return elements.stream(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TStreamOverSpliterator.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TStreamOverSpliterator.java new file mode 100644 index 000000000..92006c5fa --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TStreamOverSpliterator.java @@ -0,0 +1,63 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.Spliterator; +import java.util.function.Consumer; +import java.util.function.Predicate; + +public class TStreamOverSpliterator extends TSimpleStreamImpl { + private Spliterator spliterator; + + public TStreamOverSpliterator(Spliterator spliterator) { + this.spliterator = spliterator; + } + + @Override + public boolean next(Predicate consumer) { + AdapterAction action = new AdapterAction<>(consumer); + while (spliterator.tryAdvance(action)) { + if (!action.wantsMore) { + return true; + } + } + return false; + } + + static class AdapterAction implements Consumer { + private Predicate consumer; + boolean wantsMore; + + AdapterAction(Predicate consumer) { + this.consumer = consumer; + } + + @Override + public void accept(T t) { + wantsMore = consumer.test(t); + } + } + + @Override + protected int estimateSize() { + return (int) spliterator.estimateSize(); + } + + @Override + public long count() { + return spliterator.hasCharacteristics(Spliterator.SIZED) ? (int) spliterator.estimateSize() : super.count(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TWrappingStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TWrappingStreamImpl.java new file mode 100644 index 000000000..03576c4c5 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/impl/TWrappingStreamImpl.java @@ -0,0 +1,43 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.impl; + +import java.util.function.Predicate; + +public abstract class TWrappingStreamImpl extends TSimpleStreamImpl { + TSimpleStreamImpl sourceStream; + + public TWrappingStreamImpl(TSimpleStreamImpl sourceStream) { + this.sourceStream = sourceStream; + } + + @Override + public boolean next(Predicate consumer) { + return sourceStream.next(wrap(consumer)); + } + + protected abstract Predicate wrap(Predicate consumer); + + @Override + protected int estimateSize() { + return sourceStream.estimateSize(); + } + + @Override + public void close() throws Exception { + sourceStream.close(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TArrayIntStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TArrayIntStreamImpl.java new file mode 100644 index 000000000..a9cacb8e7 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TArrayIntStreamImpl.java @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.function.IntPredicate; + +public class TArrayIntStreamImpl extends TSimpleIntStreamImpl { + private int[] array; + private int index; + private int end; + private int size; + + public TArrayIntStreamImpl(int[] array, int start, int end) { + this.array = array; + index = start; + this.end = end; + size = end - start; + } + + @Override + public boolean next(IntPredicate consumer) { + while (index < end) { + if (!consumer.test(array[index++])) { + break; + } + } + return index < end; + } + + @Override + protected int estimateSize() { + return size; + } + + @Override + public long count() { + return size; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TBoxedIntStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TBoxedIntStream.java new file mode 100644 index 000000000..c65165f75 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TBoxedIntStream.java @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.function.Predicate; +import org.teavm.classlib.java.util.stream.impl.TSimpleStreamImpl; + +public class TBoxedIntStream extends TSimpleStreamImpl { + private TSimpleIntStreamImpl source; + + public TBoxedIntStream(TSimpleIntStreamImpl source) { + this.source = source; + } + + @Override + public boolean next(Predicate consumer) { + return source.next(consumer::test); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TCloseHandlingIntStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TCloseHandlingIntStream.java new file mode 100644 index 000000000..547fff1f7 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TCloseHandlingIntStream.java @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.function.IntPredicate; + +public class TCloseHandlingIntStream extends TSimpleIntStreamImpl { + private TSimpleIntStreamImpl innerStream; + private Runnable closeHandler; + + public TCloseHandlingIntStream(TSimpleIntStreamImpl innerStream, Runnable closeHandler) { + this.innerStream = innerStream; + this.closeHandler = closeHandler; + } + + @Override + public boolean next(IntPredicate consumer) { + return innerStream.next(consumer); + } + + @Override + public void close() throws Exception { + RuntimeException previousException = null; + try { + closeHandler.run(); + } catch (RuntimeException e) { + previousException = e; + } + + try { + innerStream.close(); + } catch (RuntimeException e) { + if (previousException != null) { + e.addSuppressed(previousException); + } + throw e; + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TCountingIntConsumer.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TCountingIntConsumer.java new file mode 100644 index 000000000..045970817 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TCountingIntConsumer.java @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.function.IntPredicate; + +public class TCountingIntConsumer implements IntPredicate { + int count; + + @Override + public boolean test(int t) { + count++; + return true; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TDistinctIntStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TDistinctIntStreamImpl.java new file mode 100644 index 000000000..7d612db53 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TDistinctIntStreamImpl.java @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.HashSet; +import java.util.Set; +import java.util.function.IntPredicate; + +public class TDistinctIntStreamImpl extends TWrappingIntStreamImpl { + public TDistinctIntStreamImpl(TSimpleIntStreamImpl innerStream) { + super(innerStream); + } + + @Override + protected IntPredicate wrap(IntPredicate consumer) { + Set visited = new HashSet<>(); + return e -> { + if (!visited.add(e)) { + return true; + } + return consumer.test(e); + }; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TEmptyIntStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TEmptyIntStreamImpl.java new file mode 100644 index 000000000..ad8beacb6 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TEmptyIntStreamImpl.java @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.function.IntPredicate; + +public class TEmptyIntStreamImpl extends TSimpleIntStreamImpl { + @Override + public boolean next(IntPredicate consumer) { + return false; + } + + @Override + protected int estimateSize() { + return 0; + } + + @Override + public long count() { + return 1; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TFilteringIntStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TFilteringIntStreamImpl.java new file mode 100644 index 000000000..2eb927948 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TFilteringIntStreamImpl.java @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.function.IntPredicate; + +public class TFilteringIntStreamImpl extends TWrappingIntStreamImpl { + private IntPredicate filter; + + public TFilteringIntStreamImpl(TSimpleIntStreamImpl innerStream, IntPredicate filter) { + super(innerStream); + this.filter = filter; + } + + @Override + protected IntPredicate wrap(IntPredicate consumer) { + return t -> { + if (!filter.test(t)) { + return true; + } + return consumer.test(t); + }; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TFindFirstIntConsumer.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TFindFirstIntConsumer.java new file mode 100644 index 000000000..2cde38156 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TFindFirstIntConsumer.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.function.IntPredicate; + +public class TFindFirstIntConsumer implements IntPredicate { + public int result; + boolean hasAny; + + @Override + public boolean test(int t) { + hasAny = true; + result = t; + return false; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TFlatMappingIntStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TFlatMappingIntStreamImpl.java new file mode 100644 index 000000000..06f48ac41 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TFlatMappingIntStreamImpl.java @@ -0,0 +1,81 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.PrimitiveIterator; +import java.util.function.IntFunction; +import java.util.function.IntPredicate; +import org.teavm.classlib.java.util.stream.TIntStream; + +public class TFlatMappingIntStreamImpl extends TSimpleIntStreamImpl { + private TSimpleIntStreamImpl sourceStream; + private TIntStream current; + private PrimitiveIterator.OfInt iterator; + private IntFunction mapper; + private boolean done; + + public TFlatMappingIntStreamImpl(TSimpleIntStreamImpl sourceStream, IntFunction mapper) { + this.sourceStream = sourceStream; + this.mapper = mapper; + } + + @Override + public boolean next(IntPredicate consumer) { + while (true) { + if (current == null) { + if (done) { + return false; + } + boolean hasMore = sourceStream.next(e -> { + current = mapper.apply(e); + return false; + }); + if (!hasMore) { + done = true; + } + if (current == null) { + done = true; + return false; + } + } + if (current instanceof TSimpleIntStreamImpl) { + @SuppressWarnings("unchecked") + TSimpleIntStreamImpl castCurrent = (TSimpleIntStreamImpl) current; + if (castCurrent.next(consumer)) { + return true; + } + current = null; + } else { + iterator = current.iterator(); + while (iterator.hasNext()) { + int e = iterator.nextInt(); + if (!consumer.test(e)) { + return true; + } + } + iterator = null; + current = null; + } + } + } + + @Override + public void close() throws Exception { + current = null; + iterator = null; + sourceStream.close(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TGenerateIntStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TGenerateIntStream.java new file mode 100644 index 000000000..547b10797 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TGenerateIntStream.java @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.function.IntPredicate; +import java.util.function.IntSupplier; + +public class TGenerateIntStream extends TSimpleIntStreamImpl { + private IntSupplier s; + + public TGenerateIntStream(IntSupplier s) { + this.s = s; + } + + @Override + public boolean next(IntPredicate consumer) { + while (consumer.test(s.getAsInt())) { + // go on + } + return true; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TGenericConcatIntStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TGenericConcatIntStream.java new file mode 100644 index 000000000..599e54e0d --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TGenericConcatIntStream.java @@ -0,0 +1,75 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.PrimitiveIterator; +import java.util.function.IntPredicate; +import org.teavm.classlib.java.util.stream.TIntStream; + +public class TGenericConcatIntStream extends TSimpleIntStreamImpl { + TIntStream first; + TIntStream second; + PrimitiveIterator.OfInt iterator; + boolean isSecond; + + public TGenericConcatIntStream(TIntStream first, TIntStream second) { + this.first = first; + this.second = second; + } + + @Override + public boolean next(IntPredicate consumer) { + if (iterator == null) { + iterator = first.iterator(); + } + while (true) { + while (iterator.hasNext()) { + if (!consumer.test(iterator.nextInt())) { + return true; + } + } + if (!isSecond) { + isSecond = true; + iterator = second.iterator(); + } else { + return false; + } + } + } + + @Override + public long count() { + return first.count() + second.count(); + } + + @Override + public void close() throws Exception { + Exception suppressed = null; + try { + first.close(); + } catch (Exception e) { + suppressed = e; + } + try { + second.close(); + } catch (Exception e) { + if (suppressed != null) { + e.addSuppressed(suppressed); + } + throw e; + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TIntAsDoubleStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TIntAsDoubleStream.java new file mode 100644 index 000000000..af28294cb --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TIntAsDoubleStream.java @@ -0,0 +1,47 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.function.DoublePredicate; +import org.teavm.classlib.java.util.stream.doubleimpl.TSimpleDoubleStreamImpl; + +public class TIntAsDoubleStream extends TSimpleDoubleStreamImpl { + private TSimpleIntStreamImpl source; + + public TIntAsDoubleStream(TSimpleIntStreamImpl source) { + this.source = source; + } + + @Override + public boolean next(DoublePredicate consumer) { + return source.next(consumer::test); + } + + @Override + protected int estimateSize() { + return source.estimateSize(); + } + + @Override + public long count() { + return source.count(); + } + + @Override + public void close() throws Exception { + source.close(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TIntAsLongStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TIntAsLongStream.java new file mode 100644 index 000000000..f0c608d65 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TIntAsLongStream.java @@ -0,0 +1,47 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.function.LongPredicate; +import org.teavm.classlib.java.util.stream.longimpl.TSimpleLongStreamImpl; + +public class TIntAsLongStream extends TSimpleLongStreamImpl { + private TSimpleIntStreamImpl source; + + public TIntAsLongStream(TSimpleIntStreamImpl source) { + this.source = source; + } + + @Override + public boolean next(LongPredicate consumer) { + return source.next(consumer::test); + } + + @Override + protected int estimateSize() { + return source.estimateSize(); + } + + @Override + public long count() { + return source.count(); + } + + @Override + public void close() throws Exception { + source.close(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TIntStreamBuilder.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TIntStreamBuilder.java new file mode 100644 index 000000000..df7c0bf88 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TIntStreamBuilder.java @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.Arrays; +import org.teavm.classlib.java.util.stream.TIntStream; + +public class TIntStreamBuilder implements TIntStream.Builder { + private int[] elements = new int[4]; + private int size; + + @Override + public void accept(int t) { + if (size == elements.length) { + elements = Arrays.copyOf(elements, elements.length * 2); + } + elements[size++] = t; + } + + @Override + public TIntStream build() { + return new TArrayIntStreamImpl(elements, 0, size); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TIterateIntStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TIterateIntStream.java new file mode 100644 index 000000000..5d37d0093 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TIterateIntStream.java @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.function.IntPredicate; +import java.util.function.IntUnaryOperator; + +public class TIterateIntStream extends TSimpleIntStreamImpl { + private int value; + private IntUnaryOperator f; + + public TIterateIntStream(int value, IntUnaryOperator f) { + this.value = value; + this.f = f; + } + + @Override + public boolean next(IntPredicate consumer) { + while (true) { + int valueToReport = value; + value = f.applyAsInt(value); + if (!consumer.test(valueToReport)) { + return true; + } + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TLimitingIntStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TLimitingIntStreamImpl.java new file mode 100644 index 000000000..967427abc --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TLimitingIntStreamImpl.java @@ -0,0 +1,58 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.function.IntPredicate; + +public class TLimitingIntStreamImpl extends TSimpleIntStreamImpl { + private TSimpleIntStreamImpl sourceStream; + private int limit; + private int remaining; + + public TLimitingIntStreamImpl(TSimpleIntStreamImpl sourceStream, int limit) { + this.sourceStream = sourceStream; + this.limit = limit; + remaining = limit; + } + + @Override + public boolean next(IntPredicate consumer) { + if (remaining == 0) { + return false; + } + boolean result = sourceStream.next(e -> { + if (remaining-- == 0) { + return false; + } + return consumer.test(e); + }); + if (!result) { + remaining = 0; + } + return remaining > 0; + } + + @Override + protected int estimateSize() { + int sourceEstimation = sourceStream.estimateSize(); + return sourceEstimation < 0 ? limit : Math.min(limit, sourceEstimation); + } + + @Override + public void close() throws Exception { + sourceStream.close(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TMappingIntStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TMappingIntStreamImpl.java new file mode 100644 index 000000000..e9461efe8 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TMappingIntStreamImpl.java @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.function.IntPredicate; +import java.util.function.IntUnaryOperator; + +public class TMappingIntStreamImpl extends TWrappingIntStreamImpl { + private IntUnaryOperator mapper; + + public TMappingIntStreamImpl(TSimpleIntStreamImpl sourceStream, IntUnaryOperator mapper) { + super(sourceStream); + this.mapper = mapper; + } + + @Override + protected IntPredicate wrap(IntPredicate consumer) { + return t -> consumer.test(mapper.applyAsInt(t)); + } + + @Override + public long count() { + return sourceStream.count(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TMappingToDoubleStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TMappingToDoubleStreamImpl.java new file mode 100644 index 000000000..17269f41c --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TMappingToDoubleStreamImpl.java @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.function.DoublePredicate; +import java.util.function.IntToDoubleFunction; +import org.teavm.classlib.java.util.stream.doubleimpl.TSimpleDoubleStreamImpl; + +public class TMappingToDoubleStreamImpl extends TSimpleDoubleStreamImpl { + private TSimpleIntStreamImpl source; + private IntToDoubleFunction mapper; + + public TMappingToDoubleStreamImpl(TSimpleIntStreamImpl source, IntToDoubleFunction mapper) { + this.source = source; + this.mapper = mapper; + } + + @Override + public boolean next(DoublePredicate consumer) { + return source.next(e -> consumer.test(mapper.applyAsDouble(e))); + } + + @Override + public void close() throws Exception { + source.close(); + } + + @Override + protected int estimateSize() { + return source.estimateSize(); + } + + @Override + public long count() { + return source.count(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TMappingToLongStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TMappingToLongStreamImpl.java new file mode 100644 index 000000000..677358315 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TMappingToLongStreamImpl.java @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.function.IntToLongFunction; +import java.util.function.LongPredicate; +import org.teavm.classlib.java.util.stream.longimpl.TSimpleLongStreamImpl; + +public class TMappingToLongStreamImpl extends TSimpleLongStreamImpl { + private TSimpleIntStreamImpl source; + private IntToLongFunction mapper; + + public TMappingToLongStreamImpl(TSimpleIntStreamImpl source, IntToLongFunction mapper) { + this.source = source; + this.mapper = mapper; + } + + @Override + public boolean next(LongPredicate consumer) { + return source.next(e -> consumer.test(mapper.applyAsLong(e))); + } + + @Override + public void close() throws Exception { + source.close(); + } + + @Override + protected int estimateSize() { + return source.estimateSize(); + } + + @Override + public long count() { + return source.count(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TMappingToObjStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TMappingToObjStreamImpl.java new file mode 100644 index 000000000..f87a9b38c --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TMappingToObjStreamImpl.java @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.function.IntFunction; +import java.util.function.Predicate; +import org.teavm.classlib.java.util.stream.impl.TSimpleStreamImpl; + +public class TMappingToObjStreamImpl extends TSimpleStreamImpl { + private TSimpleIntStreamImpl source; + private IntFunction mapper; + + public TMappingToObjStreamImpl(TSimpleIntStreamImpl source, IntFunction mapper) { + this.source = source; + this.mapper = mapper; + } + + @Override + public boolean next(Predicate consumer) { + return source.next(e -> consumer.test(mapper.apply(e))); + } + + @Override + public void close() throws Exception { + source.close(); + } + + @Override + protected int estimateSize() { + return source.estimateSize(); + } + + @Override + public long count() { + return source.count(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TPeekingIntStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TPeekingIntStreamImpl.java new file mode 100644 index 000000000..48cd01a36 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TPeekingIntStreamImpl.java @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.function.IntConsumer; +import java.util.function.IntPredicate; + +public class TPeekingIntStreamImpl extends TWrappingIntStreamImpl { + private IntConsumer elementConsumer; + + public TPeekingIntStreamImpl(TSimpleIntStreamImpl sourceStream, IntConsumer elementConsumer) { + super(sourceStream); + this.elementConsumer = elementConsumer; + } + + @Override + protected IntPredicate wrap(IntPredicate consumer) { + return e -> { + elementConsumer.accept(e); + return consumer.test(e); + }; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TRangeIntStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TRangeIntStream.java new file mode 100644 index 000000000..e5ec42f79 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TRangeIntStream.java @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.function.IntPredicate; + +public class TRangeIntStream extends TSimpleIntStreamImpl { + private int start; + private int end; + + public TRangeIntStream(int start, int end) { + this.start = start; + this.end = end; + } + + @Override + public boolean next(IntPredicate consumer) { + while (start < end) { + if (!consumer.test(start++)) { + return true; + } + } + return false; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TReducingIntConsumer.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TReducingIntConsumer.java new file mode 100644 index 000000000..a9b97da79 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TReducingIntConsumer.java @@ -0,0 +1,42 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.function.IntBinaryOperator; +import java.util.function.IntPredicate; + +class TReducingIntConsumer implements IntPredicate { + private IntBinaryOperator accumulator; + int result; + boolean initialized; + + TReducingIntConsumer(IntBinaryOperator accumulator, int result, boolean initialized) { + this.accumulator = accumulator; + this.result = result; + this.initialized = initialized; + } + + @Override + public boolean test(int t) { + if (!initialized) { + result = t; + initialized = true; + } else { + result = accumulator.applyAsInt(result, t); + } + return true; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TSimpleIntStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TSimpleIntStreamImpl.java new file mode 100644 index 000000000..d938fc7cb --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TSimpleIntStreamImpl.java @@ -0,0 +1,292 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.OptionalDouble; +import java.util.OptionalInt; +import java.util.PrimitiveIterator; +import java.util.Spliterator; +import java.util.function.BiConsumer; +import java.util.function.IntBinaryOperator; +import java.util.function.IntConsumer; +import java.util.function.IntFunction; +import java.util.function.IntPredicate; +import java.util.function.IntToDoubleFunction; +import java.util.function.IntToLongFunction; +import java.util.function.IntUnaryOperator; +import java.util.function.ObjIntConsumer; +import java.util.function.Supplier; +import org.teavm.classlib.java.util.stream.TDoubleStream; +import org.teavm.classlib.java.util.stream.TIntStream; +import org.teavm.classlib.java.util.stream.TLongStream; +import org.teavm.classlib.java.util.stream.TStream; + +public abstract class TSimpleIntStreamImpl implements TIntStream { + @Override + public TIntStream filter(IntPredicate predicate) { + return new TFilteringIntStreamImpl(this, predicate); + } + + @Override + public TIntStream map(IntUnaryOperator mapper) { + return new TMappingIntStreamImpl(this, mapper); + } + + @Override + public TStream mapToObj(IntFunction mapper) { + return new TMappingToObjStreamImpl<>(this, mapper); + } + + @Override + public TLongStream mapToLong(IntToLongFunction mapper) { + return new TMappingToLongStreamImpl(this, mapper); + } + + @Override + public TDoubleStream mapToDouble(IntToDoubleFunction mapper) { + return new TMappingToDoubleStreamImpl(this, mapper); + } + + @Override + public TIntStream flatMap(IntFunction mapper) { + return new TFlatMappingIntStreamImpl(this, mapper); + } + + @Override + public TIntStream distinct() { + return new TDistinctIntStreamImpl(this); + } + + @Override + public TIntStream sorted() { + int[] array = toArray(); + Arrays.sort(array); + return TIntStream.of(array); + } + + @Override + public TIntStream peek(IntConsumer action) { + return new TPeekingIntStreamImpl(this, action); + } + + @Override + public TIntStream limit(long maxSize) { + return new TLimitingIntStreamImpl(this, (int) maxSize); + } + + @Override + public TIntStream skip(long n) { + return new TSkippingIntStreamImpl(this, (int) n); + } + + @Override + public void forEach(IntConsumer action) { + forEachOrdered(action); + } + + @Override + public void forEachOrdered(IntConsumer action) { + next(e -> { + action.accept(e); + return true; + }); + } + + @Override + public int[] toArray() { + int estimatedSize = estimateSize(); + if (estimatedSize < 0) { + List list = new ArrayList<>(); + next(list::add); + int[] array = new int[list.size()]; + for (int i = 0; i < array.length; ++i) { + array[i] = list.get(i); + } + return array; + } else { + int[] array = new int[estimatedSize]; + ArrayFillingConsumer consumer = new ArrayFillingConsumer(array); + boolean wantsMore = next(consumer); + assert !wantsMore : "next() should have reported done status"; + if (consumer.index < array.length) { + array = Arrays.copyOf(array, consumer.index); + } + return array; + } + } + + @Override + public int reduce(int identity, IntBinaryOperator accumulator) { + TReducingIntConsumer consumer = new TReducingIntConsumer(accumulator, identity, true); + boolean wantsMore = next(consumer); + assert !wantsMore : "next() should have returned true"; + return consumer.result; + } + + @Override + public OptionalInt reduce(IntBinaryOperator accumulator) { + TReducingIntConsumer consumer = new TReducingIntConsumer(accumulator, 0, false); + boolean wantsMore = next(consumer); + assert !wantsMore : "next() should have returned true"; + return consumer.initialized ? OptionalInt.of(consumer.result) : OptionalInt.empty(); + } + + @Override + public R collect(Supplier supplier, ObjIntConsumer accumulator, BiConsumer combiner) { + R collection = supplier.get(); + next(e -> { + accumulator.accept(collection, e); + return true; + }); + return collection; + } + + @Override + public OptionalInt min() { + return reduce(Math::min); + } + + @Override + public OptionalInt max() { + return reduce(Math::max); + } + + @Override + public long count() { + TCountingIntConsumer consumer = new TCountingIntConsumer(); + next(consumer); + return consumer.count; + } + + @Override + public int sum() { + TSumIntConsumer consumer = new TSumIntConsumer(); + next(consumer); + return consumer.sum; + } + + @Override + public OptionalDouble average() { + TSumIntAsDoubleConsumer consumer = new TSumIntAsDoubleConsumer(); + next(consumer); + return consumer.count > 0 ? OptionalDouble.of(consumer.sum / consumer.count) : OptionalDouble.empty(); + } + + @Override + public boolean anyMatch(IntPredicate predicate) { + return next(predicate.negate()); + } + + @Override + public boolean allMatch(IntPredicate predicate) { + return !next(predicate); + } + + @Override + public boolean noneMatch(IntPredicate predicate) { + return !anyMatch(predicate); + } + + @Override + public OptionalInt findFirst() { + TFindFirstIntConsumer consumer = new TFindFirstIntConsumer(); + next(consumer); + return consumer.hasAny ? OptionalInt.of(consumer.result) : OptionalInt.empty(); + } + + @Override + public OptionalInt findAny() { + return findFirst(); + } + + @Override + public TLongStream asLongStream() { + return new TIntAsLongStream(this); + } + + @Override + public TDoubleStream asDoubleStream() { + return new TIntAsDoubleStream(this); + } + + @Override + public PrimitiveIterator.OfInt iterator() { + return new TSimpleIntStreamIterator(this); + } + + @Override + public Spliterator.OfInt spliterator() { + return new TSimpleIntStreamSpliterator(this); + } + + @Override + public TStream boxed() { + return new TBoxedIntStream(this); + } + + @Override + public boolean isParallel() { + return false; + } + + @Override + public TIntStream sequential() { + return this; + } + + @Override + public TIntStream parallel() { + return this; + } + + @Override + public TIntStream unordered() { + return this; + } + + @Override + public TIntStream onClose(Runnable closeHandler) { + return new TCloseHandlingIntStream(this, closeHandler); + } + + @Override + public void close() throws Exception { + } + + protected int estimateSize() { + return -1; + } + + public abstract boolean next(IntPredicate consumer); + + class ArrayFillingConsumer implements IntPredicate { + int[] array; + int index; + + ArrayFillingConsumer(int[] array) { + this.array = array; + } + + @Override + public boolean test(int t) { + array[index++] = t; + return true; + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TSimpleIntStreamIterator.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TSimpleIntStreamIterator.java new file mode 100644 index 000000000..c6dd23c7c --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TSimpleIntStreamIterator.java @@ -0,0 +1,65 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.NoSuchElementException; +import java.util.PrimitiveIterator; + +public class TSimpleIntStreamIterator implements PrimitiveIterator.OfInt { + private static final byte NEEDS_MORE = 0; + private static final byte HAS_DATA = 1; + private static final byte LAST_ELEMENT = 2; + private static final byte DONE = 3; + + private TSimpleIntStreamImpl stream; + private int lastElement; + private byte state; + + public TSimpleIntStreamIterator(TSimpleIntStreamImpl stream) { + this.stream = stream; + } + + @Override + public boolean hasNext() { + fetchIfNeeded(); + return state != DONE; + } + + @Override + public int nextInt() { + fetchIfNeeded(); + if (state == DONE) { + throw new NoSuchElementException(); + } + int result = lastElement; + state = state == LAST_ELEMENT ? DONE : NEEDS_MORE; + return result; + } + + private void fetchIfNeeded() { + if (state != NEEDS_MORE) { + return; + } + boolean hasMore = stream.next(e -> { + lastElement = e; + return false; + }); + state = hasMore ? HAS_DATA : LAST_ELEMENT; + if (state == LAST_ELEMENT) { + stream = null; + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TSimpleIntStreamSpliterator.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TSimpleIntStreamSpliterator.java new file mode 100644 index 000000000..ed99714e7 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TSimpleIntStreamSpliterator.java @@ -0,0 +1,63 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.Spliterator; +import java.util.function.IntConsumer; + +public class TSimpleIntStreamSpliterator implements Spliterator.OfInt { + private TSimpleIntStreamImpl stream; + private boolean done; + + public TSimpleIntStreamSpliterator(TSimpleIntStreamImpl stream) { + this.stream = stream; + } + + @Override + public void forEachRemaining(IntConsumer action) { + stream.next(x -> { + action.accept(x); + return true; + }); + } + + @Override + public boolean tryAdvance(IntConsumer action) { + if (done) { + return false; + } + done = !stream.next(x -> { + action.accept(x); + return false; + }); + return true; + } + + @Override + public Spliterator.OfInt trySplit() { + return null; + } + + @Override + public long estimateSize() { + return stream.estimateSize(); + } + + @Override + public int characteristics() { + return 0; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TSingleIntStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TSingleIntStreamImpl.java new file mode 100644 index 000000000..2f9ab4ab5 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TSingleIntStreamImpl.java @@ -0,0 +1,42 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.function.IntPredicate; + +public class TSingleIntStreamImpl extends TSimpleIntStreamImpl { + private int element; + + public TSingleIntStreamImpl(int element) { + this.element = element; + } + + @Override + public boolean next(IntPredicate consumer) { + consumer.test(element); + return false; + } + + @Override + protected int estimateSize() { + return 1; + } + + @Override + public long count() { + return 1; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TSkippingIntStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TSkippingIntStreamImpl.java new file mode 100644 index 000000000..c9cd9d9d8 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TSkippingIntStreamImpl.java @@ -0,0 +1,51 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.function.IntPredicate; + +public class TSkippingIntStreamImpl extends TSimpleIntStreamImpl { + private TSimpleIntStreamImpl sourceStream; + private int skip; + private int remaining; + + public TSkippingIntStreamImpl(TSimpleIntStreamImpl sourceStream, int skip) { + this.sourceStream = sourceStream; + this.skip = skip; + remaining = skip; + } + + @Override + public boolean next(IntPredicate consumer) { + if (remaining > 0) { + if (!sourceStream.next(e -> --remaining > 0)) { + return false; + } + } + return sourceStream.next(consumer); + } + + @Override + protected int estimateSize() { + int sourceSize = sourceStream.estimateSize(); + return sourceSize >= 0 ? Math.max(0, sourceSize - skip) : -1; + } + + @Override + public void close() throws Exception { + sourceStream.close(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TSpecializedConcatIntStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TSpecializedConcatIntStream.java new file mode 100644 index 000000000..37e7d4484 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TSpecializedConcatIntStream.java @@ -0,0 +1,78 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.function.IntPredicate; + +public class TSpecializedConcatIntStream extends TSimpleIntStreamImpl { + TSimpleIntStreamImpl first; + TSimpleIntStreamImpl second; + TSimpleIntStreamImpl current; + + public TSpecializedConcatIntStream(TSimpleIntStreamImpl first, TSimpleIntStreamImpl second) { + this.first = first; + this.second = second; + current = first; + } + + @Override + public boolean next(IntPredicate consumer) { + if (current == null) { + return false; + } + while (true) { + if (current.next(consumer)) { + return true; + } + if (current == first) { + current = second; + } else { + current = null; + return false; + } + } + } + + @Override + protected int estimateSize() { + int firstSize = first.estimateSize(); + int secondSize = second.estimateSize(); + return firstSize >= 0 && secondSize >= 0 ? firstSize + secondSize : -1; + } + + @Override + public long count() { + return first.count() + second.count(); + } + + @Override + public void close() throws Exception { + RuntimeException suppressed = null; + try { + first.close(); + } catch (RuntimeException e) { + suppressed = e; + } + try { + second.close(); + } catch (RuntimeException e) { + if (suppressed != null) { + e.addSuppressed(suppressed); + } + throw e; + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TSumIntAsDoubleConsumer.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TSumIntAsDoubleConsumer.java new file mode 100644 index 000000000..c07cdd2b4 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TSumIntAsDoubleConsumer.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.function.IntPredicate; + +public class TSumIntAsDoubleConsumer implements IntPredicate { + double sum; + int count; + + @Override + public boolean test(int t) { + sum += t; + count++; + return true; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TSumIntConsumer.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TSumIntConsumer.java new file mode 100644 index 000000000..a3358377a --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TSumIntConsumer.java @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.function.IntPredicate; + +public class TSumIntConsumer implements IntPredicate { + int sum; + + @Override + public boolean test(int t) { + sum += t; + return true; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TWrappingIntStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TWrappingIntStreamImpl.java new file mode 100644 index 000000000..e6ed26f96 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/intimpl/TWrappingIntStreamImpl.java @@ -0,0 +1,43 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.intimpl; + +import java.util.function.IntPredicate; + +public abstract class TWrappingIntStreamImpl extends TSimpleIntStreamImpl { + TSimpleIntStreamImpl sourceStream; + + public TWrappingIntStreamImpl(TSimpleIntStreamImpl sourceStream) { + this.sourceStream = sourceStream; + } + + @Override + public boolean next(IntPredicate consumer) { + return sourceStream.next(wrap(consumer)); + } + + protected abstract IntPredicate wrap(IntPredicate consumer); + + @Override + protected int estimateSize() { + return sourceStream.estimateSize(); + } + + @Override + public void close() throws Exception { + sourceStream.close(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TArrayLongStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TArrayLongStreamImpl.java new file mode 100644 index 000000000..b3eb57b5a --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TArrayLongStreamImpl.java @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.function.LongPredicate; + +public class TArrayLongStreamImpl extends TSimpleLongStreamImpl { + private long[] array; + private int index; + private int end; + private int size; + + public TArrayLongStreamImpl(long[] array, int start, int end) { + this.array = array; + index = start; + this.end = end; + size = end - start; + } + + @Override + public boolean next(LongPredicate consumer) { + while (index < end) { + if (!consumer.test(array[index++])) { + break; + } + } + return index < end; + } + + @Override + protected int estimateSize() { + return size; + } + + @Override + public long count() { + return size; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TBoxedLongStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TBoxedLongStream.java new file mode 100644 index 000000000..a8923e3d0 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TBoxedLongStream.java @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.function.Predicate; +import org.teavm.classlib.java.util.stream.impl.TSimpleStreamImpl; + +public class TBoxedLongStream extends TSimpleStreamImpl { + private TSimpleLongStreamImpl source; + + public TBoxedLongStream(TSimpleLongStreamImpl source) { + this.source = source; + } + + @Override + public boolean next(Predicate consumer) { + return source.next(consumer::test); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TCloseHandlingLongStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TCloseHandlingLongStream.java new file mode 100644 index 000000000..ea7b2c508 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TCloseHandlingLongStream.java @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.function.LongPredicate; + +public class TCloseHandlingLongStream extends TSimpleLongStreamImpl { + private TSimpleLongStreamImpl innerStream; + private Runnable closeHandler; + + public TCloseHandlingLongStream(TSimpleLongStreamImpl innerStream, Runnable closeHandler) { + this.innerStream = innerStream; + this.closeHandler = closeHandler; + } + + @Override + public boolean next(LongPredicate consumer) { + return innerStream.next(consumer); + } + + @Override + public void close() throws Exception { + RuntimeException previousException = null; + try { + closeHandler.run(); + } catch (RuntimeException e) { + previousException = e; + } + + try { + innerStream.close(); + } catch (RuntimeException e) { + if (previousException != null) { + e.addSuppressed(previousException); + } + throw e; + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TCountingLongConsumer.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TCountingLongConsumer.java new file mode 100644 index 000000000..12acc16da --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TCountingLongConsumer.java @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.function.LongPredicate; + +public class TCountingLongConsumer implements LongPredicate { + int count; + + @Override + public boolean test(long t) { + count++; + return true; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TDistinctLongStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TDistinctLongStreamImpl.java new file mode 100644 index 000000000..6d1bb00ca --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TDistinctLongStreamImpl.java @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.HashSet; +import java.util.Set; +import java.util.function.LongPredicate; + +public class TDistinctLongStreamImpl extends TWrappingLongStreamImpl { + public TDistinctLongStreamImpl(TSimpleLongStreamImpl innerStream) { + super(innerStream); + } + + @Override + protected LongPredicate wrap(LongPredicate consumer) { + Set visited = new HashSet<>(); + return e -> { + if (!visited.add(e)) { + return true; + } + return consumer.test(e); + }; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TEmptyLongStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TEmptyLongStreamImpl.java new file mode 100644 index 000000000..96ec04b0f --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TEmptyLongStreamImpl.java @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.function.LongPredicate; + +public class TEmptyLongStreamImpl extends TSimpleLongStreamImpl { + @Override + public boolean next(LongPredicate consumer) { + return false; + } + + @Override + protected int estimateSize() { + return 0; + } + + @Override + public long count() { + return 1; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TFilteringLongStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TFilteringLongStreamImpl.java new file mode 100644 index 000000000..86532d9a1 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TFilteringLongStreamImpl.java @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.function.LongPredicate; + +public class TFilteringLongStreamImpl extends TWrappingLongStreamImpl { + private LongPredicate filter; + + public TFilteringLongStreamImpl(TSimpleLongStreamImpl innerStream, LongPredicate filter) { + super(innerStream); + this.filter = filter; + } + + @Override + protected LongPredicate wrap(LongPredicate consumer) { + return t -> { + if (!filter.test(t)) { + return true; + } + return consumer.test(t); + }; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TFindFirstLongConsumer.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TFindFirstLongConsumer.java new file mode 100644 index 000000000..f9959012f --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TFindFirstLongConsumer.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.function.LongPredicate; + +public class TFindFirstLongConsumer implements LongPredicate { + public long result; + boolean hasAny; + + @Override + public boolean test(long t) { + hasAny = true; + result = t; + return false; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TFlatMappingLongStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TFlatMappingLongStreamImpl.java new file mode 100644 index 000000000..cd5709a24 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TFlatMappingLongStreamImpl.java @@ -0,0 +1,81 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.PrimitiveIterator; +import java.util.function.LongFunction; +import java.util.function.LongPredicate; +import org.teavm.classlib.java.util.stream.TLongStream; + +public class TFlatMappingLongStreamImpl extends TSimpleLongStreamImpl { + private TSimpleLongStreamImpl sourceStream; + private TLongStream current; + private PrimitiveIterator.OfLong iterator; + private LongFunction mapper; + private boolean done; + + public TFlatMappingLongStreamImpl(TSimpleLongStreamImpl sourceStream, LongFunction mapper) { + this.sourceStream = sourceStream; + this.mapper = mapper; + } + + @Override + public boolean next(LongPredicate consumer) { + while (true) { + if (current == null) { + if (done) { + return false; + } + boolean hasMore = sourceStream.next(e -> { + current = mapper.apply(e); + return false; + }); + if (!hasMore) { + done = true; + } + if (current == null) { + done = true; + return false; + } + } + if (current instanceof TSimpleLongStreamImpl) { + @SuppressWarnings("unchecked") + TSimpleLongStreamImpl castCurrent = (TSimpleLongStreamImpl) current; + if (castCurrent.next(consumer)) { + return true; + } + current = null; + } else { + iterator = current.iterator(); + while (iterator.hasNext()) { + long e = iterator.nextLong(); + if (!consumer.test(e)) { + return true; + } + } + iterator = null; + current = null; + } + } + } + + @Override + public void close() throws Exception { + current = null; + iterator = null; + sourceStream.close(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TGenerateLongStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TGenerateLongStream.java new file mode 100644 index 000000000..4f9814c35 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TGenerateLongStream.java @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.function.LongPredicate; +import java.util.function.LongSupplier; + +public class TGenerateLongStream extends TSimpleLongStreamImpl { + private LongSupplier s; + + public TGenerateLongStream(LongSupplier s) { + this.s = s; + } + + @Override + public boolean next(LongPredicate consumer) { + while (consumer.test(s.getAsLong())) { + // go on + } + return true; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TGenericConcatLongStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TGenericConcatLongStream.java new file mode 100644 index 000000000..7782c9dd1 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TGenericConcatLongStream.java @@ -0,0 +1,75 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.PrimitiveIterator; +import java.util.function.LongPredicate; +import org.teavm.classlib.java.util.stream.TLongStream; + +public class TGenericConcatLongStream extends TSimpleLongStreamImpl { + TLongStream first; + TLongStream second; + PrimitiveIterator.OfLong iterator; + boolean isSecond; + + public TGenericConcatLongStream(TLongStream first, TLongStream second) { + this.first = first; + this.second = second; + } + + @Override + public boolean next(LongPredicate consumer) { + if (iterator == null) { + iterator = first.iterator(); + } + while (true) { + while (iterator.hasNext()) { + if (!consumer.test(iterator.nextLong())) { + return true; + } + } + if (!isSecond) { + isSecond = true; + iterator = second.iterator(); + } else { + return false; + } + } + } + + @Override + public long count() { + return first.count() + second.count(); + } + + @Override + public void close() throws Exception { + Exception suppressed = null; + try { + first.close(); + } catch (Exception e) { + suppressed = e; + } + try { + second.close(); + } catch (Exception e) { + if (suppressed != null) { + e.addSuppressed(suppressed); + } + throw e; + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TIterateLongStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TIterateLongStream.java new file mode 100644 index 000000000..d7c2e58f6 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TIterateLongStream.java @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.function.LongPredicate; +import java.util.function.LongUnaryOperator; + +public class TIterateLongStream extends TSimpleLongStreamImpl { + private long value; + private LongUnaryOperator f; + + public TIterateLongStream(long value, LongUnaryOperator f) { + this.value = value; + this.f = f; + } + + @Override + public boolean next(LongPredicate consumer) { + while (true) { + long valueToReport = value; + value = f.applyAsLong(value); + if (!consumer.test(valueToReport)) { + return true; + } + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TLimitingLongStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TLimitingLongStreamImpl.java new file mode 100644 index 000000000..1d987d802 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TLimitingLongStreamImpl.java @@ -0,0 +1,58 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.function.LongPredicate; + +public class TLimitingLongStreamImpl extends TSimpleLongStreamImpl { + private TSimpleLongStreamImpl sourceStream; + private int limit; + private int remaining; + + public TLimitingLongStreamImpl(TSimpleLongStreamImpl sourceStream, int limit) { + this.sourceStream = sourceStream; + this.limit = limit; + remaining = limit; + } + + @Override + public boolean next(LongPredicate consumer) { + if (remaining == 0) { + return false; + } + boolean result = sourceStream.next(e -> { + if (remaining-- == 0) { + return false; + } + return consumer.test(e); + }); + if (!result) { + remaining = 0; + } + return remaining > 0; + } + + @Override + protected int estimateSize() { + int sourceEstimation = sourceStream.estimateSize(); + return sourceEstimation < 0 ? limit : Math.min(limit, sourceEstimation); + } + + @Override + public void close() throws Exception { + sourceStream.close(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TLongAsDoubleStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TLongAsDoubleStream.java new file mode 100644 index 000000000..0bf68284b --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TLongAsDoubleStream.java @@ -0,0 +1,47 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.function.DoublePredicate; +import org.teavm.classlib.java.util.stream.doubleimpl.TSimpleDoubleStreamImpl; + +public class TLongAsDoubleStream extends TSimpleDoubleStreamImpl { + private TSimpleLongStreamImpl source; + + public TLongAsDoubleStream(TSimpleLongStreamImpl source) { + this.source = source; + } + + @Override + public boolean next(DoublePredicate consumer) { + return source.next(consumer::test); + } + + @Override + protected int estimateSize() { + return source.estimateSize(); + } + + @Override + public long count() { + return source.count(); + } + + @Override + public void close() throws Exception { + source.close(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TLongStreamBuilder.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TLongStreamBuilder.java new file mode 100644 index 000000000..dc77db013 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TLongStreamBuilder.java @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.Arrays; +import org.teavm.classlib.java.util.stream.TLongStream; + +public class TLongStreamBuilder implements TLongStream.Builder { + private long[] elements = new long[4]; + private int size; + + @Override + public void accept(long t) { + if (size == elements.length) { + elements = Arrays.copyOf(elements, elements.length * 2); + } + elements[size++] = t; + } + + @Override + public TLongStream build() { + return new TArrayLongStreamImpl(elements, 0, size); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TMappingLongStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TMappingLongStreamImpl.java new file mode 100644 index 000000000..a1fb4e262 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TMappingLongStreamImpl.java @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.function.LongPredicate; +import java.util.function.LongUnaryOperator; + +public class TMappingLongStreamImpl extends TWrappingLongStreamImpl { + private LongUnaryOperator mapper; + + public TMappingLongStreamImpl(TSimpleLongStreamImpl sourceStream, LongUnaryOperator mapper) { + super(sourceStream); + this.mapper = mapper; + } + + @Override + protected LongPredicate wrap(LongPredicate consumer) { + return t -> consumer.test(mapper.applyAsLong(t)); + } + + @Override + public long count() { + return sourceStream.count(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TMappingToDoubleStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TMappingToDoubleStreamImpl.java new file mode 100644 index 000000000..55953ec5c --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TMappingToDoubleStreamImpl.java @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.function.DoublePredicate; +import java.util.function.LongToDoubleFunction; +import org.teavm.classlib.java.util.stream.doubleimpl.TSimpleDoubleStreamImpl; + +public class TMappingToDoubleStreamImpl extends TSimpleDoubleStreamImpl { + private TSimpleLongStreamImpl source; + private LongToDoubleFunction mapper; + + public TMappingToDoubleStreamImpl(TSimpleLongStreamImpl source, LongToDoubleFunction mapper) { + this.source = source; + this.mapper = mapper; + } + + @Override + public boolean next(DoublePredicate consumer) { + return source.next(e -> consumer.test(mapper.applyAsDouble(e))); + } + + @Override + public void close() throws Exception { + source.close(); + } + + @Override + protected int estimateSize() { + return source.estimateSize(); + } + + @Override + public long count() { + return source.count(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TMappingToIntStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TMappingToIntStreamImpl.java new file mode 100644 index 000000000..7dc90ea19 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TMappingToIntStreamImpl.java @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.function.IntPredicate; +import java.util.function.LongToIntFunction; +import org.teavm.classlib.java.util.stream.intimpl.TSimpleIntStreamImpl; + +public class TMappingToIntStreamImpl extends TSimpleIntStreamImpl { + private TSimpleLongStreamImpl source; + private LongToIntFunction mapper; + + public TMappingToIntStreamImpl(TSimpleLongStreamImpl source, LongToIntFunction mapper) { + this.source = source; + this.mapper = mapper; + } + + @Override + public boolean next(IntPredicate consumer) { + return source.next(e -> consumer.test(mapper.applyAsInt(e))); + } + + @Override + public void close() throws Exception { + source.close(); + } + + @Override + protected int estimateSize() { + return source.estimateSize(); + } + + @Override + public long count() { + return source.count(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TMappingToObjStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TMappingToObjStreamImpl.java new file mode 100644 index 000000000..92d773f26 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TMappingToObjStreamImpl.java @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.function.LongFunction; +import java.util.function.Predicate; +import org.teavm.classlib.java.util.stream.impl.TSimpleStreamImpl; + +public class TMappingToObjStreamImpl extends TSimpleStreamImpl { + private TSimpleLongStreamImpl source; + private LongFunction mapper; + + public TMappingToObjStreamImpl(TSimpleLongStreamImpl source, LongFunction mapper) { + this.source = source; + this.mapper = mapper; + } + + @Override + public boolean next(Predicate consumer) { + return source.next(e -> consumer.test(mapper.apply(e))); + } + + @Override + public void close() throws Exception { + source.close(); + } + + @Override + protected int estimateSize() { + return source.estimateSize(); + } + + @Override + public long count() { + return source.count(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TPeekingLongStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TPeekingLongStreamImpl.java new file mode 100644 index 000000000..c4f70f4ef --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TPeekingLongStreamImpl.java @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.function.LongConsumer; +import java.util.function.LongPredicate; + +public class TPeekingLongStreamImpl extends TWrappingLongStreamImpl { + private LongConsumer elementConsumer; + + public TPeekingLongStreamImpl(TSimpleLongStreamImpl sourceStream, LongConsumer elementConsumer) { + super(sourceStream); + this.elementConsumer = elementConsumer; + } + + @Override + protected LongPredicate wrap(LongPredicate consumer) { + return e -> { + elementConsumer.accept(e); + return consumer.test(e); + }; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TRangeLongStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TRangeLongStream.java new file mode 100644 index 000000000..d8e08aa1f --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TRangeLongStream.java @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.function.LongPredicate; + +public class TRangeLongStream extends TSimpleLongStreamImpl { + private long start; + private long end; + + public TRangeLongStream(long start, long end) { + this.start = start; + this.end = end; + } + + @Override + public boolean next(LongPredicate consumer) { + while (start < end) { + if (!consumer.test(start++)) { + return true; + } + } + return false; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TReducingLongConsumer.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TReducingLongConsumer.java new file mode 100644 index 000000000..24ccdb106 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TReducingLongConsumer.java @@ -0,0 +1,42 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.function.LongBinaryOperator; +import java.util.function.LongPredicate; + +class TReducingLongConsumer implements LongPredicate { + private LongBinaryOperator accumulator; + long result; + boolean initialized; + + TReducingLongConsumer(LongBinaryOperator accumulator, long result, boolean initialized) { + this.accumulator = accumulator; + this.result = result; + this.initialized = initialized; + } + + @Override + public boolean test(long t) { + if (!initialized) { + result = t; + initialized = true; + } else { + result = accumulator.applyAsLong(result, t); + } + return true; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TSimpleLongStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TSimpleLongStreamImpl.java new file mode 100644 index 000000000..dd4462ac4 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TSimpleLongStreamImpl.java @@ -0,0 +1,287 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.OptionalDouble; +import java.util.OptionalLong; +import java.util.PrimitiveIterator; +import java.util.Spliterator; +import java.util.function.BiConsumer; +import java.util.function.LongBinaryOperator; +import java.util.function.LongConsumer; +import java.util.function.LongFunction; +import java.util.function.LongPredicate; +import java.util.function.LongToDoubleFunction; +import java.util.function.LongToIntFunction; +import java.util.function.LongUnaryOperator; +import java.util.function.ObjLongConsumer; +import java.util.function.Supplier; +import org.teavm.classlib.java.util.stream.TDoubleStream; +import org.teavm.classlib.java.util.stream.TIntStream; +import org.teavm.classlib.java.util.stream.TLongStream; +import org.teavm.classlib.java.util.stream.TStream; + +public abstract class TSimpleLongStreamImpl implements TLongStream { + @Override + public TLongStream filter(LongPredicate predicate) { + return new TFilteringLongStreamImpl(this, predicate); + } + + @Override + public TLongStream map(LongUnaryOperator mapper) { + return new TMappingLongStreamImpl(this, mapper); + } + + @Override + public TStream mapToObj(LongFunction mapper) { + return new TMappingToObjStreamImpl<>(this, mapper); + } + + @Override + public TIntStream mapToInt(LongToIntFunction mapper) { + return new TMappingToIntStreamImpl(this, mapper); + } + + @Override + public TDoubleStream mapToDouble(LongToDoubleFunction mapper) { + return new TMappingToDoubleStreamImpl(this, mapper); + } + + @Override + public TLongStream flatMap(LongFunction mapper) { + return new TFlatMappingLongStreamImpl(this, mapper); + } + + @Override + public TLongStream distinct() { + return new TDistinctLongStreamImpl(this); + } + + @Override + public TLongStream sorted() { + long[] array = toArray(); + Arrays.sort(array); + return TLongStream.of(array); + } + + @Override + public TLongStream peek(LongConsumer action) { + return new TPeekingLongStreamImpl(this, action); + } + + @Override + public TLongStream limit(long maxSize) { + return new TLimitingLongStreamImpl(this, (int) maxSize); + } + + @Override + public TLongStream skip(long n) { + return new TSkippingLongStreamImpl(this, (int) n); + } + + @Override + public void forEach(LongConsumer action) { + forEachOrdered(action); + } + + @Override + public void forEachOrdered(LongConsumer action) { + next(e -> { + action.accept(e); + return true; + }); + } + + @Override + public long[] toArray() { + int estimatedSize = estimateSize(); + if (estimatedSize < 0) { + List list = new ArrayList<>(); + next(list::add); + long[] array = new long[list.size()]; + for (int i = 0; i < array.length; ++i) { + array[i] = list.get(i); + } + return array; + } else { + long[] array = new long[estimatedSize]; + ArrayFillingConsumer consumer = new ArrayFillingConsumer(array); + boolean wantsMore = next(consumer); + assert !wantsMore : "next() should have reported done status"; + if (consumer.index < array.length) { + array = Arrays.copyOf(array, consumer.index); + } + return array; + } + } + + @Override + public long reduce(long identity, LongBinaryOperator accumulator) { + TReducingLongConsumer consumer = new TReducingLongConsumer(accumulator, identity, true); + boolean wantsMore = next(consumer); + assert !wantsMore : "next() should have returned true"; + return consumer.result; + } + + @Override + public OptionalLong reduce(LongBinaryOperator accumulator) { + TReducingLongConsumer consumer = new TReducingLongConsumer(accumulator, 0, false); + boolean wantsMore = next(consumer); + assert !wantsMore : "next() should have returned true"; + return consumer.initialized ? OptionalLong.of(consumer.result) : OptionalLong.empty(); + } + + @Override + public R collect(Supplier supplier, ObjLongConsumer accumulator, BiConsumer combiner) { + R collection = supplier.get(); + next(e -> { + accumulator.accept(collection, e); + return true; + }); + return collection; + } + + @Override + public OptionalLong min() { + return reduce(Math::min); + } + + @Override + public OptionalLong max() { + return reduce(Math::max); + } + + @Override + public long count() { + TCountingLongConsumer consumer = new TCountingLongConsumer(); + next(consumer); + return consumer.count; + } + + @Override + public long sum() { + TSumLongConsumer consumer = new TSumLongConsumer(); + next(consumer); + return consumer.sum; + } + + @Override + public OptionalDouble average() { + TSumLongAsDoubleConsumer consumer = new TSumLongAsDoubleConsumer(); + next(consumer); + return consumer.count > 0 ? OptionalDouble.of(consumer.sum / consumer.count) : OptionalDouble.empty(); + } + + @Override + public boolean anyMatch(LongPredicate predicate) { + return next(predicate.negate()); + } + + @Override + public boolean allMatch(LongPredicate predicate) { + return !next(predicate); + } + + @Override + public boolean noneMatch(LongPredicate predicate) { + return !anyMatch(predicate); + } + + @Override + public OptionalLong findFirst() { + TFindFirstLongConsumer consumer = new TFindFirstLongConsumer(); + next(consumer); + return consumer.hasAny ? OptionalLong.of(consumer.result) : OptionalLong.empty(); + } + + @Override + public OptionalLong findAny() { + return findFirst(); + } + + @Override + public TDoubleStream asDoubleStream() { + return new TLongAsDoubleStream(this); + } + + @Override + public PrimitiveIterator.OfLong iterator() { + return new TSimpleLongStreamIterator(this); + } + + @Override + public Spliterator.OfLong spliterator() { + return new TSimpleLongStreamSpliterator(this); + } + + @Override + public TStream boxed() { + return new TBoxedLongStream(this); + } + + @Override + public boolean isParallel() { + return false; + } + + @Override + public TLongStream sequential() { + return this; + } + + @Override + public TLongStream parallel() { + return this; + } + + @Override + public TLongStream unordered() { + return this; + } + + @Override + public TLongStream onClose(Runnable closeHandler) { + return new TCloseHandlingLongStream(this, closeHandler); + } + + @Override + public void close() throws Exception { + } + + protected int estimateSize() { + return -1; + } + + public abstract boolean next(LongPredicate consumer); + + class ArrayFillingConsumer implements LongPredicate { + long[] array; + int index; + + ArrayFillingConsumer(long[] array) { + this.array = array; + } + + @Override + public boolean test(long t) { + array[index++] = t; + return true; + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TSimpleLongStreamIterator.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TSimpleLongStreamIterator.java new file mode 100644 index 000000000..7f9e0bb45 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TSimpleLongStreamIterator.java @@ -0,0 +1,65 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.NoSuchElementException; +import java.util.PrimitiveIterator; + +public class TSimpleLongStreamIterator implements PrimitiveIterator.OfLong { + private static final byte NEEDS_MORE = 0; + private static final byte HAS_DATA = 1; + private static final byte LAST_ELEMENT = 2; + private static final byte DONE = 3; + + private TSimpleLongStreamImpl stream; + private long lastElement; + private byte state; + + public TSimpleLongStreamIterator(TSimpleLongStreamImpl stream) { + this.stream = stream; + } + + @Override + public boolean hasNext() { + fetchIfNeeded(); + return state != DONE; + } + + @Override + public long nextLong() { + fetchIfNeeded(); + if (state == DONE) { + throw new NoSuchElementException(); + } + long result = lastElement; + state = state == LAST_ELEMENT ? DONE : NEEDS_MORE; + return result; + } + + private void fetchIfNeeded() { + if (state != NEEDS_MORE) { + return; + } + boolean hasMore = stream.next(e -> { + lastElement = e; + return false; + }); + state = hasMore ? HAS_DATA : LAST_ELEMENT; + if (state == LAST_ELEMENT) { + stream = null; + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TSimpleLongStreamSpliterator.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TSimpleLongStreamSpliterator.java new file mode 100644 index 000000000..8e0df0cb3 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TSimpleLongStreamSpliterator.java @@ -0,0 +1,63 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.Spliterator; +import java.util.function.LongConsumer; + +public class TSimpleLongStreamSpliterator implements Spliterator.OfLong { + private TSimpleLongStreamImpl stream; + private boolean done; + + public TSimpleLongStreamSpliterator(TSimpleLongStreamImpl stream) { + this.stream = stream; + } + + @Override + public void forEachRemaining(LongConsumer action) { + stream.next(x -> { + action.accept(x); + return true; + }); + } + + @Override + public boolean tryAdvance(LongConsumer action) { + if (done) { + return false; + } + done = !stream.next(x -> { + action.accept(x); + return false; + }); + return true; + } + + @Override + public OfLong trySplit() { + return null; + } + + @Override + public long estimateSize() { + return stream.estimateSize(); + } + + @Override + public int characteristics() { + return 0; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TSingleLongStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TSingleLongStreamImpl.java new file mode 100644 index 000000000..31f2fa3e4 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TSingleLongStreamImpl.java @@ -0,0 +1,42 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.function.LongPredicate; + +public class TSingleLongStreamImpl extends TSimpleLongStreamImpl { + private long element; + + public TSingleLongStreamImpl(long element) { + this.element = element; + } + + @Override + public boolean next(LongPredicate consumer) { + consumer.test(element); + return false; + } + + @Override + protected int estimateSize() { + return 1; + } + + @Override + public long count() { + return 1; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TSkippingLongStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TSkippingLongStreamImpl.java new file mode 100644 index 000000000..1a9b560da --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TSkippingLongStreamImpl.java @@ -0,0 +1,51 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.function.LongPredicate; + +public class TSkippingLongStreamImpl extends TSimpleLongStreamImpl { + private TSimpleLongStreamImpl sourceStream; + private int skip; + private int remaining; + + public TSkippingLongStreamImpl(TSimpleLongStreamImpl sourceStream, int skip) { + this.sourceStream = sourceStream; + this.skip = skip; + remaining = skip; + } + + @Override + public boolean next(LongPredicate consumer) { + if (remaining > 0) { + if (!sourceStream.next(e -> --remaining > 0)) { + return false; + } + } + return sourceStream.next(consumer); + } + + @Override + protected int estimateSize() { + int sourceSize = sourceStream.estimateSize(); + return sourceSize >= 0 ? Math.max(0, sourceSize - skip) : -1; + } + + @Override + public void close() throws Exception { + sourceStream.close(); + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TSpecializedConcatLongStream.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TSpecializedConcatLongStream.java new file mode 100644 index 000000000..00ac7a5e8 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TSpecializedConcatLongStream.java @@ -0,0 +1,78 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.function.LongPredicate; + +public class TSpecializedConcatLongStream extends TSimpleLongStreamImpl { + TSimpleLongStreamImpl first; + TSimpleLongStreamImpl second; + TSimpleLongStreamImpl current; + + public TSpecializedConcatLongStream(TSimpleLongStreamImpl first, TSimpleLongStreamImpl second) { + this.first = first; + this.second = second; + current = first; + } + + @Override + public boolean next(LongPredicate consumer) { + if (current == null) { + return false; + } + while (true) { + if (current.next(consumer)) { + return true; + } + if (current == first) { + current = second; + } else { + current = null; + return false; + } + } + } + + @Override + protected int estimateSize() { + int firstSize = first.estimateSize(); + int secondSize = second.estimateSize(); + return firstSize >= 0 && secondSize >= 0 ? firstSize + secondSize : -1; + } + + @Override + public long count() { + return first.count() + second.count(); + } + + @Override + public void close() throws Exception { + RuntimeException suppressed = null; + try { + first.close(); + } catch (RuntimeException e) { + suppressed = e; + } + try { + second.close(); + } catch (RuntimeException e) { + if (suppressed != null) { + e.addSuppressed(suppressed); + } + throw e; + } + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TSumLongAsDoubleConsumer.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TSumLongAsDoubleConsumer.java new file mode 100644 index 000000000..40c090050 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TSumLongAsDoubleConsumer.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.function.LongPredicate; + +public class TSumLongAsDoubleConsumer implements LongPredicate { + double sum; + int count; + + @Override + public boolean test(long t) { + sum += t; + count++; + return true; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TSumLongConsumer.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TSumLongConsumer.java new file mode 100644 index 000000000..bd9ef20b6 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TSumLongConsumer.java @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.function.LongPredicate; + +public class TSumLongConsumer implements LongPredicate { + long sum; + + @Override + public boolean test(long t) { + sum += t; + return true; + } +} diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TWrappingLongStreamImpl.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TWrappingLongStreamImpl.java new file mode 100644 index 000000000..929c05ee8 --- /dev/null +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/longimpl/TWrappingLongStreamImpl.java @@ -0,0 +1,43 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream.longimpl; + +import java.util.function.LongPredicate; + +public abstract class TWrappingLongStreamImpl extends TSimpleLongStreamImpl { + TSimpleLongStreamImpl sourceStream; + + public TWrappingLongStreamImpl(TSimpleLongStreamImpl sourceStream) { + this.sourceStream = sourceStream; + } + + @Override + public boolean next(LongPredicate consumer) { + return sourceStream.next(wrap(consumer)); + } + + protected abstract LongPredicate wrap(LongPredicate consumer); + + @Override + protected int estimateSize() { + return sourceStream.estimateSize(); + } + + @Override + public void close() throws Exception { + sourceStream.close(); + } +} diff --git a/tests/src/test/java/org/teavm/classlib/java/util/ArraysTest.java b/tests/src/test/java/org/teavm/classlib/java/util/ArraysTest.java index 3b8deb1d8..76cb5b64a 100644 --- a/tests/src/test/java/org/teavm/classlib/java/util/ArraysTest.java +++ b/tests/src/test/java/org/teavm/classlib/java/util/ArraysTest.java @@ -18,6 +18,7 @@ package org.teavm.classlib.java.util; import static org.junit.Assert.assertEquals; import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; import org.junit.Test; import org.junit.runner.RunWith; import org.teavm.junit.TeaVMTestRunner; @@ -63,4 +64,60 @@ public class ArraysTest { array[3] = array; assertEquals("[1, 2, null, [...], foo]", Arrays.deepToString(array)); } + + @Test + public void objectStream() { + String[] array = { "foo", "bar", "baz" }; + + String result = Arrays.stream(array).collect(Collectors.joining(",")); + assertEquals("foo,bar,baz", result); + + result = Arrays.stream(array, 1, 3).collect(Collectors.joining(",")); + assertEquals("bar,baz", result); + + result = Arrays.stream(array, 0, 2).collect(Collectors.joining(",")); + assertEquals("foo,bar", result); + } + + @Test + public void intStream() { + int[] array = { 23, 42, 55 }; + + String result = Arrays.stream(array).mapToObj(Integer::toString).collect(Collectors.joining(",")); + assertEquals("23,42,55", result); + + result = Arrays.stream(array, 1, 3).mapToObj(Integer::toString).collect(Collectors.joining(",")); + assertEquals("42,55", result); + + result = Arrays.stream(array, 0, 2).mapToObj(Integer::toString).collect(Collectors.joining(",")); + assertEquals("23,42", result); + } + + @Test + public void longStream() { + long[] array = { 23, 42, 55 }; + + String result = Arrays.stream(array).mapToObj(Long::toString).collect(Collectors.joining(",")); + assertEquals("23,42,55", result); + + result = Arrays.stream(array, 1, 3).mapToObj(Long::toString).collect(Collectors.joining(",")); + assertEquals("42,55", result); + + result = Arrays.stream(array, 0, 2).mapToObj(Long::toString).collect(Collectors.joining(",")); + assertEquals("23,42", result); + } + + @Test + public void doubleStream() { + double[] array = { 23, 42, 55 }; + + String result = Arrays.stream(array).mapToObj(Double::toString).collect(Collectors.joining(",")); + assertEquals("23.0,42.0,55.0", result); + + result = Arrays.stream(array, 1, 3).mapToObj(Double::toString).collect(Collectors.joining(",")); + assertEquals("42.0,55.0", result); + + result = Arrays.stream(array, 0, 2).mapToObj(Double::toString).collect(Collectors.joining(",")); + assertEquals("23.0,42.0", result); + } } diff --git a/tests/src/test/java/org/teavm/classlib/java/util/stream/CollectorsTest.java b/tests/src/test/java/org/teavm/classlib/java/util/stream/CollectorsTest.java new file mode 100644 index 000000000..9fef1929e --- /dev/null +++ b/tests/src/test/java/org/teavm/classlib/java/util/stream/CollectorsTest.java @@ -0,0 +1,58 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream; + +import static org.junit.Assert.assertEquals; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.teavm.junit.TeaVMTestRunner; + +@RunWith(TeaVMTestRunner.class) +public class CollectorsTest { + @Test + public void joining() { + assertEquals("123", Stream.of(1, 2, 3).map(Object::toString).collect(Collectors.joining())); + assertEquals("1,2,3", Stream.of(1, 2, 3).map(Object::toString).collect(Collectors.joining(","))); + assertEquals("[1,2,3]", Stream.of(1, 2, 3).map(Object::toString).collect(Collectors.joining(",", "[", "]"))); + assertEquals("", Stream.empty().map(Object::toString).collect(Collectors.joining(","))); + assertEquals("[]", Stream.empty().map(Object::toString).collect(Collectors.joining(",", "[", "]"))); + assertEquals("1", Stream.of(1).map(Object::toString).collect(Collectors.joining(","))); + assertEquals("[1]", Stream.of(1).map(Object::toString).collect(Collectors.joining(",", "[", "]"))); + } + + @Test + public void toList() { + assertEquals(Arrays.asList(1, 2, 3), Stream.of(1, 2, 3).collect(Collectors.toList())); + } + + @Test + public void toSet() { + assertEquals(new HashSet<>(Arrays.asList(1, 2, 3)), Stream.of(1, 2, 3).collect(Collectors.toSet())); + } + + @Test + public void toCollection() { + List c = new ArrayList<>(); + Stream.of(1, 2, 3).collect(Collectors.toCollection(() -> c)); + assertEquals(Arrays.asList(1, 2, 3), c); + } +} diff --git a/tests/src/test/java/org/teavm/classlib/java/util/stream/DoubleStreamTest.java b/tests/src/test/java/org/teavm/classlib/java/util/stream/DoubleStreamTest.java new file mode 100644 index 000000000..baee5ead5 --- /dev/null +++ b/tests/src/test/java/org/teavm/classlib/java/util/stream/DoubleStreamTest.java @@ -0,0 +1,338 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import java.util.PrimitiveIterator; +import java.util.Spliterator; +import java.util.function.DoubleConsumer; +import java.util.function.IntConsumer; +import java.util.function.LongConsumer; +import java.util.stream.Collectors; +import java.util.stream.DoubleStream; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.teavm.junit.TeaVMTestRunner; + +@RunWith(TeaVMTestRunner.class) +public class DoubleStreamTest { + @Test + public void forEachWorks() { + StringBuilder sb = new StringBuilder(); + DoubleStream.of(1, 2, 3).forEach(appendNumbersTo(sb)); + assertEquals("1.0;2.0;3.0;", sb.toString()); + } + + @Test + public void mapWorks() { + StringBuilder sb = new StringBuilder(); + DoubleStream.of(1, 2, 3).map(n -> n * n).forEach(appendNumbersTo(sb)); + assertEquals("1.0;4.0;9.0;", sb.toString()); + } + + @Test + public void mapToObjWorks() { + String result = DoubleStream.of(1, 2, 3).mapToObj(n -> String.valueOf(n * n)).collect(Collectors.joining(";")); + assertEquals("1.0;4.0;9.0", result); + } + + @Test + public void mapToIntWorks() { + StringBuilder sb = new StringBuilder(); + DoubleStream.of(1, 2, 3).mapToInt(n -> (int) (n * n)).forEach(appendIntNumbersTo(sb)); + assertEquals("1;4;9;", sb.toString()); + } + + @Test + public void mapToLongWorks() { + StringBuilder sb = new StringBuilder(); + DoubleStream.of(1, 2, 3).mapToLong(n -> (long) (n * n)).forEach(appendLongNumbersTo(sb)); + assertEquals("1;4;9;", sb.toString()); + } + + @Test + public void filterWorks() { + StringBuilder sb = new StringBuilder(); + DoubleStream.of(1, 2, 3, 4, 5, 6).filter(n -> (n % 2) == 0).forEach(appendNumbersTo(sb)); + assertEquals("2.0;4.0;6.0;", sb.toString()); + } + + @Test + public void flatMapWorks() { + StringBuilder sb = new StringBuilder(); + DoubleStream.of(1, 3).flatMap(n -> DoubleStream.of(n, n + 1)).forEach(appendNumbersTo(sb)); + assertEquals("1.0;2.0;3.0;4.0;", sb.toString()); + + sb.setLength(0); + DoubleStream.of(1, 3).flatMap(n -> DoubleStream.of(n, n + 1)).skip(1).forEach(appendNumbersTo(sb)); + assertEquals("2.0;3.0;4.0;", sb.toString()); + + sb.setLength(0); + DoubleStream.of(1, 4).flatMap(n -> DoubleStream.of(n, n + 1, n + 2)).skip(4).forEach(appendNumbersTo(sb)); + assertEquals("5.0;6.0;", sb.toString()); + } + + @Test + public void skipWorks() { + for (int i = 0; i <= 6; ++i) { + StringBuilder sb = new StringBuilder(); + DoubleStream.iterate(1, n -> n + 1).limit(5).skip(i).forEach(appendNumbersTo(sb)); + + StringBuilder expected = new StringBuilder(); + for (int j = i; j < 5; ++j) { + expected.append((double) j + 1).append(';'); + } + assertEquals("Error skipping " + i + " elements", expected.toString(), sb.toString()); + } + } + + @Test + public void limitWorks() { + for (int i = 0; i <= 3; ++i) { + StringBuilder sb = new StringBuilder(); + DoubleStream.iterate(1, n -> n + 1).limit(i).forEach(appendNumbersTo(sb)); + + StringBuilder expected = new StringBuilder(); + for (int j = 0; j < i; ++j) { + expected.append((double) j + 1).append(';'); + } + assertEquals("Error limiting to " + i + " elements", expected.toString(), sb.toString()); + } + } + + @Test + public void countWorks() { + assertEquals(4, DoubleStream.of(2, 3, 2, 3).count()); + assertEquals(3, DoubleStream.of(2, 3, 2, 3).limit(3).count()); + assertEquals(4, DoubleStream.of(2, 3, 2, 3).limit(5).count()); + assertEquals(0, DoubleStream.of(2, 3, 2, 3).skip(5).count()); + assertEquals(3, DoubleStream.of(2, 3, 2, 3).skip(1).count()); + + assertEquals(2, DoubleStream.of(2, 3, 2, 3).filter(n -> n == 2).count()); + + assertEquals(10, DoubleStream.generate(() -> 1).limit(10).count()); + assertEquals(10, DoubleStream.generate(() -> 1).limit(10).count()); + + assertEquals(4, DoubleStream.of(1, 3).flatMap(n -> DoubleStream.of(n, n + 1)).count()); + } + + @Test + public void distinctWorks() { + StringBuilder sb = new StringBuilder(); + DoubleStream.of(2, 3, 2, 3).distinct().forEach(appendNumbersTo(sb)); + assertEquals("2.0;3.0;", sb.toString()); + + sb.setLength(0); + DoubleStream.of(2, 3, 2, 3).skip(1).distinct().forEach(appendNumbersTo(sb)); + assertEquals("3.0;2.0;", sb.toString()); + + sb.setLength(0); + DoubleStream.of(2, 3, 2, 3).limit(2).distinct().forEach(appendNumbersTo(sb)); + assertEquals("2.0;3.0;", sb.toString()); + + sb.setLength(0); + DoubleStream.of(2, 2, 3, 2, 4, 3, 1).distinct().forEach(appendNumbersTo(sb)); + assertEquals("2.0;3.0;4.0;1.0;", sb.toString()); + } + + @Test + public void findFirstWorks() { + assertEquals(2, DoubleStream.of(2, 3).findFirst().getAsDouble(), 0.001); + assertEquals(3, DoubleStream.of(2, 3).skip(1).findFirst().getAsDouble(), 0.001); + assertEquals(4, DoubleStream.of(2, 3, 4, 5).filter(n -> n > 3).findFirst().getAsDouble(), 0.001); + assertFalse(DoubleStream.of(2, 3, 4, 5).filter(n -> n > 10).findFirst().isPresent()); + assertFalse(DoubleStream.of(2, 3).skip(3).findFirst().isPresent()); + assertEquals(20, DoubleStream.of(2, 3).map(n -> n * 10).findFirst().getAsDouble(), 0.001); + } + + @Test + public void concatWorks() { + StringBuilder sb = new StringBuilder(); + DoubleStream.concat(DoubleStream.of(1, 2), DoubleStream.of(3, 4)).forEach(appendNumbersTo(sb)); + assertEquals("1.0;2.0;3.0;4.0;", sb.toString()); + + sb.setLength(0); + DoubleStream.concat(DoubleStream.of(1, 2), DoubleStream.of(3, 4)).skip(1).forEach(appendNumbersTo(sb)); + assertEquals("2.0;3.0;4.0;", sb.toString()); + + sb.setLength(0); + DoubleStream.concat(DoubleStream.of(1, 2), DoubleStream.of(3, 4, 5)).skip(3).forEach(appendNumbersTo(sb)); + assertEquals("4.0;5.0;", sb.toString()); + } + + @Test + public void peekWorks() { + StringBuilder sb = new StringBuilder(); + DoubleStream.of(1, 2, 3).peek(appendNumbersTo(sb)).map(n -> n + 10).forEach(appendNumbersTo(sb)); + assertEquals("1.0;11.0;2.0;12.0;3.0;13.0;", sb.toString()); + } + + @Test + public void reduceWorks() { + assertEquals(10, DoubleStream.of(1, 2, 3, 4).reduce(0, (a, b) -> a + b), 0.001); + assertEquals(0, DoubleStream.of(1, 2, 3, 4).skip(4).reduce(0, (a, b) -> a + b), 0.001); + assertEquals(720, DoubleStream.iterate(1, n -> n + 1).limit(6).reduce(1, (a, b) -> a * b), 0.001); + + assertEquals(9, DoubleStream.of(1, 2, 3, 4).skip(1).reduce((a, b) -> a + b).getAsDouble(), 0.001); + assertFalse(DoubleStream.of(1, 2, 3, 4).skip(4).reduce((a, b) -> a + b).isPresent()); + } + + @Test + public void streamOfOneElement() { + StringBuilder sb = new StringBuilder(); + DoubleStream.of(5).forEach(appendNumbersTo(sb)); + assertEquals("5.0;", sb.toString()); + + sb.setLength(0); + DoubleStream.of(5).skip(1).forEach(appendNumbersTo(sb)); + assertEquals("", sb.toString()); + + sb.setLength(0); + DoubleStream.concat(DoubleStream.of(5), DoubleStream.of(6)).forEach(appendNumbersTo(sb)); + assertEquals("5.0;6.0;", sb.toString()); + } + + @Test + public void sortedStream() { + StringBuilder sb = new StringBuilder(); + DoubleStream.of(5, 7, 1, 2, 4, 3).sorted().forEach(appendNumbersTo(sb)); + assertEquals("1.0;2.0;3.0;4.0;5.0;7.0;", sb.toString()); + + sb.setLength(0); + DoubleStream.of(2, 3, 1).peek(appendNumbersTo(sb)).sorted().limit(2).map(n -> n + 10) + .forEach(appendNumbersTo(sb)); + assertEquals("2.0;3.0;1.0;11.0;12.0;", sb.toString()); + + sb.setLength(0); + DoubleStream.of(2, 3, 1).peek(appendNumbersTo(sb)).sorted().limit(0).forEach(appendNumbersTo(sb)); + assertEquals("2.0;3.0;1.0;", sb.toString()); + } + + @Test + public void minMax() { + assertEquals(3, DoubleStream.of(5, 7, 3, 6).min().getAsDouble(), 0.001); + assertEquals(7, DoubleStream.of(5, 7, 3, 6).max().getAsDouble(), 0.001); + + assertEquals(3, DoubleStream.of(5, 7, 3, 6).skip(1).min().getAsDouble(), 0.001); + assertEquals(7, DoubleStream.of(5, 7, 3, 6).skip(1).max().getAsDouble(), 0.001); + + assertEquals(3, DoubleStream.of(5, 7, 3, 6).skip(2).min().getAsDouble(), 0.001); + assertEquals(6, DoubleStream.of(5, 7, 3, 6).skip(2).max().getAsDouble(), 0.001); + + assertEquals(6, DoubleStream.of(5, 7, 3, 6).skip(3).min().getAsDouble(), 0.001); + assertEquals(6, DoubleStream.of(5, 7, 3, 6).skip(3).max().getAsDouble(), 0.001); + + assertFalse(DoubleStream.empty().min().isPresent()); + assertFalse(DoubleStream.empty().max().isPresent()); + } + + @Test + public void allNoneAny() { + assertTrue(DoubleStream.of(5, 7, 3, 6).anyMatch(n -> n == 7)); + assertFalse(DoubleStream.of(5, 7, 3, 6).anyMatch(n -> n == 11)); + assertFalse(DoubleStream.empty().anyMatch(n -> true)); + + assertFalse(DoubleStream.of(5, 7, 3, 6).noneMatch(n -> n == 7)); + assertTrue(DoubleStream.of(5, 7, 3, 6).noneMatch(n -> n == 11)); + assertTrue(DoubleStream.empty().noneMatch(n -> true)); + + assertTrue(DoubleStream.of(5, 7, 3, 6).allMatch(n -> n < 10)); + assertFalse(DoubleStream.of(5, 7, 3, 6).allMatch(n -> n < 6)); + assertTrue(DoubleStream.empty().allMatch(n -> false)); + } + + @Test + public void closeFlatMap() { + int[] closed = new int[3]; + + DoubleStream.of(0, 1) + .flatMap(n -> DoubleStream.of(n, n + 1).onClose(() -> closed[(int) n]++)) + .onClose(() -> closed[2]++) + .skip(10).close(); + + assertArrayEquals(new int[] { 0, 0, 1 }, closed); + } + + @Test + public void closeMap() { + int[] closed = new int[2]; + DoubleStream.of(1, 2).onClose(() -> closed[0]++).map(x -> x * 2).onClose(() -> closed[1]++).close(); + assertArrayEquals(new int[] { 1, 1 }, closed); + } + + @Test + public void closeConcat() { + int[] closed = new int[3]; + + DoubleStream.concat( + DoubleStream.of(1, 2).onClose(() -> closed[0]++), + DoubleStream.of(3, 4).onClose(() -> closed[1]++) + ).onClose(() -> closed[2]++).close(); + + assertArrayEquals(new int[] { 1, 1, 1 }, closed); + } + + @Test + public void iterator() { + StringBuilder sb = new StringBuilder(); + PrimitiveIterator.OfDouble iterator = DoubleStream.of(1, 2, 3).iterator(); + while (iterator.hasNext()) { + sb.append(iterator.next()).append(';'); + } + assertEquals("1.0;2.0;3.0;", sb.toString()); + + sb.setLength(0); + iterator = DoubleStream.of(1, 2, 3).iterator(); + iterator.forEachRemaining(appendNumbersTo(sb)); + assertEquals("1.0;2.0;3.0;", sb.toString()); + } + + @Test + public void spliterator() { + StringBuilder sb = new StringBuilder(); + Spliterator.OfDouble spliterator = DoubleStream.of(1, 2, 3).spliterator(); + while (spliterator.tryAdvance(appendNumbersTo(sb))) { + // continue + } + assertEquals("1.0;2.0;3.0;", sb.toString()); + + sb.setLength(0); + spliterator = DoubleStream.of(1, 2, 3).spliterator(); + spliterator.forEachRemaining(appendNumbersTo(sb)); + assertEquals("1.0;2.0;3.0;", sb.toString()); + } + + @Test + public void average() { + assertEquals(2.5, DoubleStream.of(1, 2, 3, 4).average().getAsDouble(), 0.001); + assertFalse(DoubleStream.empty().average().isPresent()); + } + + private DoubleConsumer appendNumbersTo(StringBuilder sb) { + return n -> sb.append(n).append(';'); + } + + private IntConsumer appendIntNumbersTo(StringBuilder sb) { + return n -> sb.append(n).append(';'); + } + + private LongConsumer appendLongNumbersTo(StringBuilder sb) { + return n -> sb.append(n).append(';'); + } +} diff --git a/tests/src/test/java/org/teavm/classlib/java/util/stream/IntStreamTest.java b/tests/src/test/java/org/teavm/classlib/java/util/stream/IntStreamTest.java new file mode 100644 index 000000000..9652771c9 --- /dev/null +++ b/tests/src/test/java/org/teavm/classlib/java/util/stream/IntStreamTest.java @@ -0,0 +1,337 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import java.util.PrimitiveIterator; +import java.util.Spliterator; +import java.util.function.DoubleConsumer; +import java.util.function.IntConsumer; +import java.util.function.LongConsumer; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.teavm.junit.TeaVMTestRunner; + +@RunWith(TeaVMTestRunner.class) +public class IntStreamTest { + @Test + public void forEachWorks() { + StringBuilder sb = new StringBuilder(); + IntStream.of(1, 2, 3).forEach(appendNumbersTo(sb)); + assertEquals("1;2;3;", sb.toString()); + } + + @Test + public void mapWorks() { + StringBuilder sb = new StringBuilder(); + IntStream.of(1, 2, 3).map(n -> n * n).forEach(appendNumbersTo(sb)); + assertEquals("1;4;9;", sb.toString()); + } + + @Test + public void mapToObjWorks() { + String result = IntStream.of(1, 2, 3).mapToObj(n -> String.valueOf(n * n)).collect(Collectors.joining(";")); + assertEquals("1;4;9", result); + } + + @Test + public void mapToLongWorks() { + StringBuilder sb = new StringBuilder(); + IntStream.of(1, 2, 3).mapToLong(n -> n * n).forEach(appendLongNumbersTo(sb)); + assertEquals("1;4;9;", sb.toString()); + } + + @Test + public void mapToDoubleWorks() { + StringBuilder sb = new StringBuilder(); + IntStream.of(1, 2, 3).mapToDouble(n -> n * n).forEach(appendDoubleNumbersTo(sb)); + assertEquals("1.0;4.0;9.0;", sb.toString()); + } + + @Test + public void filterWorks() { + StringBuilder sb = new StringBuilder(); + IntStream.of(1, 2, 3, 4, 5, 6).filter(n -> (n & 1) == 0).forEach(appendNumbersTo(sb)); + assertEquals("2;4;6;", sb.toString()); + } + + @Test + public void flatMapWorks() { + StringBuilder sb = new StringBuilder(); + IntStream.of(1, 3).flatMap(n -> IntStream.of(n, n + 1)).forEach(appendNumbersTo(sb)); + assertEquals("1;2;3;4;", sb.toString()); + + sb.setLength(0); + IntStream.of(1, 3).flatMap(n -> IntStream.of(n, n + 1)).skip(1).forEach(appendNumbersTo(sb)); + assertEquals("2;3;4;", sb.toString()); + + sb.setLength(0); + IntStream.of(1, 4).flatMap(n -> IntStream.of(n, n + 1, n + 2)).skip(4).forEach(appendNumbersTo(sb)); + assertEquals("5;6;", sb.toString()); + } + + @Test + public void skipWorks() { + for (int i = 0; i <= 6; ++i) { + StringBuilder sb = new StringBuilder(); + IntStream.iterate(1, n -> n + 1).limit(5).skip(i).forEach(appendNumbersTo(sb)); + + StringBuilder expected = new StringBuilder(); + for (int j = i; j < 5; ++j) { + expected.append(j + 1).append(';'); + } + assertEquals("Error skipping " + i + " elements", expected.toString(), sb.toString()); + } + } + + @Test + public void limitWorks() { + for (int i = 0; i <= 3; ++i) { + StringBuilder sb = new StringBuilder(); + IntStream.iterate(1, n -> n + 1).limit(i).forEach(appendNumbersTo(sb)); + + StringBuilder expected = new StringBuilder(); + for (int j = 0; j < i; ++j) { + expected.append(j + 1).append(';'); + } + assertEquals("Error limiting to " + i + " elements", expected.toString(), sb.toString()); + } + } + + @Test + public void countWorks() { + assertEquals(4, IntStream.of(2, 3, 2, 3).count()); + assertEquals(3, IntStream.of(2, 3, 2, 3).limit(3).count()); + assertEquals(4, IntStream.of(2, 3, 2, 3).limit(5).count()); + assertEquals(0, IntStream.of(2, 3, 2, 3).skip(5).count()); + assertEquals(3, IntStream.of(2, 3, 2, 3).skip(1).count()); + + assertEquals(2, IntStream.of(2, 3, 2, 3).filter(n -> n == 2).count()); + + assertEquals(10, IntStream.generate(() -> 1).limit(10).count()); + assertEquals(10, IntStream.generate(() -> 1).limit(10).count()); + + assertEquals(4, IntStream.of(1, 3).flatMap(n -> IntStream.of(n, n + 1)).count()); + } + + @Test + public void distinctWorks() { + assertArrayEquals(new int[] { 2, 3 }, IntStream.of(2, 3, 2, 3).distinct().toArray()); + assertArrayEquals(new int[] { 3, 2 }, IntStream.of(2, 3, 2, 3).skip(1).distinct().toArray()); + assertArrayEquals(new int[] { 2, 3 }, IntStream.of(2, 3, 2, 3).limit(2).distinct().toArray()); + assertArrayEquals(new int[] { 2, 3, 4, 1 }, IntStream.of(2, 2, 3, 2, 4, 3, 1).distinct().toArray()); + } + + @Test + public void findFirstWorks() { + assertEquals(2, IntStream.of(2, 3).findFirst().getAsInt()); + assertEquals(3, IntStream.of(2, 3).skip(1).findFirst().getAsInt()); + assertEquals(4, IntStream.of(2, 3, 4, 5).filter(n -> n > 3).findFirst().getAsInt()); + assertFalse(IntStream.of(2, 3, 4, 5).filter(n -> n > 10).findFirst().isPresent()); + assertFalse(IntStream.of(2, 3).skip(3).findFirst().isPresent()); + assertEquals(20, IntStream.of(2, 3).map(n -> n * 10).findFirst().getAsInt()); + } + + @Test + public void concatWorks() { + StringBuilder sb = new StringBuilder(); + IntStream.concat(IntStream.of(1, 2), IntStream.of(3, 4)).forEach(appendNumbersTo(sb)); + assertEquals("1;2;3;4;", sb.toString()); + + sb.setLength(0); + IntStream.concat(IntStream.of(1, 2), IntStream.of(3, 4)).skip(1).forEach(appendNumbersTo(sb)); + assertEquals("2;3;4;", sb.toString()); + + sb.setLength(0); + IntStream.concat(IntStream.of(1, 2), IntStream.of(3, 4, 5)).skip(3).forEach(appendNumbersTo(sb)); + assertEquals("4;5;", sb.toString()); + } + + @Test + public void peekWorks() { + StringBuilder sb = new StringBuilder(); + IntStream.of(1, 2, 3).peek(appendNumbersTo(sb)).map(n -> n + 10).forEach(appendNumbersTo(sb)); + assertEquals("1;11;2;12;3;13;", sb.toString()); + } + + @Test + public void reduceWorks() { + assertEquals(10, IntStream.of(1, 2, 3, 4).reduce(0, (a, b) -> a + b)); + assertEquals(0, IntStream.of(1, 2, 3, 4).skip(4).reduce(0, (a, b) -> a + b)); + assertEquals(720, IntStream.iterate(1, n -> n + 1).limit(6).reduce(1, (a, b) -> a * b)); + + assertEquals(9, IntStream.of(1, 2, 3, 4).skip(1).reduce((a, b) -> a + b).getAsInt()); + assertFalse(IntStream.of(1, 2, 3, 4).skip(4).reduce((a, b) -> a + b).isPresent()); + } + + @Test + public void streamOfOneElement() { + StringBuilder sb = new StringBuilder(); + IntStream.of(5).forEach(appendNumbersTo(sb)); + assertEquals("5;", sb.toString()); + + sb.setLength(0); + IntStream.of(5).skip(1).forEach(appendNumbersTo(sb)); + assertEquals("", sb.toString()); + + sb.setLength(0); + IntStream.concat(IntStream.of(5), IntStream.of(6)).forEach(appendNumbersTo(sb)); + assertEquals("5;6;", sb.toString()); + } + + @Test + public void sortedStream() { + StringBuilder sb = new StringBuilder(); + IntStream.of(5, 7, 1, 2, 4, 3).sorted().forEach(appendNumbersTo(sb)); + assertEquals("1;2;3;4;5;7;", sb.toString()); + + sb.setLength(0); + IntStream.of(2, 3, 1).peek(appendNumbersTo(sb)).sorted().limit(2).map(n -> n + 10).forEach(appendNumbersTo(sb)); + assertEquals("2;3;1;11;12;", sb.toString()); + + sb.setLength(0); + IntStream.of(2, 3, 1).peek(appendNumbersTo(sb)).sorted().limit(0).forEach(appendNumbersTo(sb)); + assertEquals("2;3;1;", sb.toString()); + } + + @Test + public void minMax() { + assertEquals(3, IntStream.of(5, 7, 3, 6).min().getAsInt()); + assertEquals(7, IntStream.of(5, 7, 3, 6).max().getAsInt()); + + assertEquals(3, IntStream.of(5, 7, 3, 6).skip(1).min().getAsInt()); + assertEquals(7, IntStream.of(5, 7, 3, 6).skip(1).max().getAsInt()); + + assertEquals(3, IntStream.of(5, 7, 3, 6).skip(2).min().getAsInt()); + assertEquals(6, IntStream.of(5, 7, 3, 6).skip(2).max().getAsInt()); + + assertEquals(6, IntStream.of(5, 7, 3, 6).skip(3).min().getAsInt()); + assertEquals(6, IntStream.of(5, 7, 3, 6).skip(3).max().getAsInt()); + + assertFalse(IntStream.empty().min().isPresent()); + assertFalse(IntStream.empty().max().isPresent()); + } + + @Test + public void allNoneAny() { + assertTrue(IntStream.of(5, 7, 3, 6).anyMatch(n -> n == 7)); + assertFalse(IntStream.of(5, 7, 3, 6).anyMatch(n -> n == 11)); + assertFalse(IntStream.empty().anyMatch(n -> true)); + + assertFalse(IntStream.of(5, 7, 3, 6).noneMatch(n -> n == 7)); + assertTrue(IntStream.of(5, 7, 3, 6).noneMatch(n -> n == 11)); + assertTrue(IntStream.empty().noneMatch(n -> true)); + + assertTrue(IntStream.of(5, 7, 3, 6).allMatch(n -> n < 10)); + assertFalse(IntStream.of(5, 7, 3, 6).allMatch(n -> n < 6)); + assertTrue(IntStream.empty().allMatch(n -> false)); + } + + @Test + public void closeFlatMap() { + int[] closed = new int[3]; + + IntStream.of(0, 1) + .flatMap(n -> IntStream.of(n, n + 1).onClose(() -> closed[n]++)) + .onClose(() -> closed[2]++) + .skip(10).close(); + + assertArrayEquals(new int[] { 0, 0, 1 }, closed); + } + + @Test + public void closeMap() { + int[] closed = new int[2]; + IntStream.of(1, 2).onClose(() -> closed[0]++).map(x -> x * 2).onClose(() -> closed[1]++).close(); + assertArrayEquals(new int[] { 1, 1 }, closed); + } + + @Test + public void closeConcat() { + int[] closed = new int[3]; + + IntStream.concat( + IntStream.of(1, 2).onClose(() -> closed[0]++), + IntStream.of(3, 4).onClose(() -> closed[1]++) + ).onClose(() -> closed[2]++).close(); + + assertArrayEquals(new int[] { 1, 1, 1 }, closed); + } + + @Test + public void iterator() { + StringBuilder sb = new StringBuilder(); + PrimitiveIterator.OfInt iterator = IntStream.of(1, 2, 3).iterator(); + while (iterator.hasNext()) { + sb.append(iterator.next()).append(';'); + } + assertEquals("1;2;3;", sb.toString()); + + sb.setLength(0); + iterator = IntStream.of(1, 2, 3).iterator(); + iterator.forEachRemaining(appendNumbersTo(sb)); + assertEquals("1;2;3;", sb.toString()); + } + + @Test + public void spliterator() { + StringBuilder sb = new StringBuilder(); + Spliterator.OfInt spliterator = IntStream.of(1, 2, 3).spliterator(); + while (spliterator.tryAdvance(appendNumbersTo(sb))) { + // continue + } + assertEquals("1;2;3;", sb.toString()); + + sb.setLength(0); + spliterator = IntStream.of(1, 2, 3).spliterator(); + spliterator.forEachRemaining(appendNumbersTo(sb)); + assertEquals("1;2;3;", sb.toString()); + } + + @Test + public void average() { + assertEquals(2.5, IntStream.of(1, 2, 3, 4).average().getAsDouble(), 0.001); + assertFalse(IntStream.empty().average().isPresent()); + } + + @Test + public void range() { + StringBuilder sb = new StringBuilder(); + IntStream.range(1, 4).forEach(appendNumbersTo(sb)); + assertEquals("1;2;3;", sb.toString()); + + sb.setLength(0); + IntStream.rangeClosed(1, 4).forEach(appendNumbersTo(sb)); + assertEquals("1;2;3;4;", sb.toString()); + } + + private IntConsumer appendNumbersTo(StringBuilder sb) { + return n -> sb.append(n).append(';'); + } + + private LongConsumer appendLongNumbersTo(StringBuilder sb) { + return n -> sb.append(n).append(';'); + } + + private DoubleConsumer appendDoubleNumbersTo(StringBuilder sb) { + return n -> sb.append(n).append(';'); + } +} diff --git a/tests/src/test/java/org/teavm/classlib/java/util/stream/LongStreamTest.java b/tests/src/test/java/org/teavm/classlib/java/util/stream/LongStreamTest.java new file mode 100644 index 000000000..cd18c2bf0 --- /dev/null +++ b/tests/src/test/java/org/teavm/classlib/java/util/stream/LongStreamTest.java @@ -0,0 +1,338 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import java.util.PrimitiveIterator; +import java.util.Spliterator; +import java.util.function.DoubleConsumer; +import java.util.function.IntConsumer; +import java.util.function.LongConsumer; +import java.util.stream.Collectors; +import java.util.stream.LongStream; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.teavm.junit.TeaVMTestRunner; + +@RunWith(TeaVMTestRunner.class) +public class LongStreamTest { + @Test + public void forEachWorks() { + StringBuilder sb = new StringBuilder(); + LongStream.of(1, 2, 3).forEach(appendNumbersTo(sb)); + assertEquals("1;2;3;", sb.toString()); + } + + @Test + public void mapWorks() { + StringBuilder sb = new StringBuilder(); + LongStream.of(1, 2, 3).map(n -> n * n).forEach(appendNumbersTo(sb)); + assertEquals("1;4;9;", sb.toString()); + } + + @Test + public void mapToObjWorks() { + String result = LongStream.of(1, 2, 3).mapToObj(n -> String.valueOf(n * n)).collect(Collectors.joining(";")); + assertEquals("1;4;9", result); + } + + @Test + public void mapToIntWorks() { + StringBuilder sb = new StringBuilder(); + LongStream.of(1, 2, 3).mapToInt(n -> (int) (n * n)).forEach(appendIntNumbersTo(sb)); + assertEquals("1;4;9;", sb.toString()); + } + + @Test + public void mapToDoubleWorks() { + StringBuilder sb = new StringBuilder(); + LongStream.of(1, 2, 3).mapToDouble(n -> n * n).forEach(appendDoubleNumbersTo(sb)); + assertEquals("1.0;4.0;9.0;", sb.toString()); + } + + @Test + public void filterWorks() { + StringBuilder sb = new StringBuilder(); + LongStream.of(1, 2, 3, 4, 5, 6).filter(n -> (n & 1) == 0).forEach(appendNumbersTo(sb)); + assertEquals("2;4;6;", sb.toString()); + } + + @Test + public void flatMapWorks() { + StringBuilder sb = new StringBuilder(); + LongStream.of(1, 3).flatMap(n -> LongStream.of(n, n + 1)).forEach(appendNumbersTo(sb)); + assertEquals("1;2;3;4;", sb.toString()); + + sb.setLength(0); + LongStream.of(1, 3).flatMap(n -> LongStream.of(n, n + 1)).skip(1).forEach(appendNumbersTo(sb)); + assertEquals("2;3;4;", sb.toString()); + + sb.setLength(0); + LongStream.of(1, 4).flatMap(n -> LongStream.of(n, n + 1, n + 2)).skip(4).forEach(appendNumbersTo(sb)); + assertEquals("5;6;", sb.toString()); + } + + @Test + public void skipWorks() { + for (int i = 0; i <= 6; ++i) { + StringBuilder sb = new StringBuilder(); + LongStream.iterate(1, n -> n + 1).limit(5).skip(i).forEach(appendNumbersTo(sb)); + + StringBuilder expected = new StringBuilder(); + for (int j = i; j < 5; ++j) { + expected.append(j + 1).append(';'); + } + assertEquals("Error skipping " + i + " elements", expected.toString(), sb.toString()); + } + } + + @Test + public void limitWorks() { + for (int i = 0; i <= 3; ++i) { + StringBuilder sb = new StringBuilder(); + LongStream.iterate(1, n -> n + 1).limit(i).forEach(appendNumbersTo(sb)); + + StringBuilder expected = new StringBuilder(); + for (int j = 0; j < i; ++j) { + expected.append(j + 1).append(';'); + } + assertEquals("Error limiting to " + i + " elements", expected.toString(), sb.toString()); + } + } + + @Test + public void countWorks() { + assertEquals(4, LongStream.of(2, 3, 2, 3).count()); + assertEquals(3, LongStream.of(2, 3, 2, 3).limit(3).count()); + assertEquals(4, LongStream.of(2, 3, 2, 3).limit(5).count()); + assertEquals(0, LongStream.of(2, 3, 2, 3).skip(5).count()); + assertEquals(3, LongStream.of(2, 3, 2, 3).skip(1).count()); + + assertEquals(2, LongStream.of(2, 3, 2, 3).filter(n -> n == 2).count()); + + assertEquals(10, LongStream.generate(() -> 1).limit(10).count()); + assertEquals(10, LongStream.generate(() -> 1).limit(10).count()); + + assertEquals(4, LongStream.of(1, 3).flatMap(n -> LongStream.of(n, n + 1)).count()); + } + + @Test + public void distinctWorks() { + assertArrayEquals(new long[] { 2, 3 }, LongStream.of(2, 3, 2, 3).distinct().toArray()); + assertArrayEquals(new long[] { 3, 2 }, LongStream.of(2, 3, 2, 3).skip(1).distinct().toArray()); + assertArrayEquals(new long[] { 2, 3 }, LongStream.of(2, 3, 2, 3).limit(2).distinct().toArray()); + assertArrayEquals(new long[] { 2, 3, 4, 1 }, LongStream.of(2, 2, 3, 2, 4, 3, 1).distinct().toArray()); + } + + @Test + public void findFirstWorks() { + assertEquals(2, LongStream.of(2, 3).findFirst().getAsLong()); + assertEquals(3, LongStream.of(2, 3).skip(1).findFirst().getAsLong()); + assertEquals(4, LongStream.of(2, 3, 4, 5).filter(n -> n > 3).findFirst().getAsLong()); + assertFalse(LongStream.of(2, 3, 4, 5).filter(n -> n > 10).findFirst().isPresent()); + assertFalse(LongStream.of(2, 3).skip(3).findFirst().isPresent()); + assertEquals(20, LongStream.of(2, 3).map(n -> n * 10).findFirst().getAsLong()); + } + + @Test + public void concatWorks() { + StringBuilder sb = new StringBuilder(); + LongStream.concat(LongStream.of(1, 2), LongStream.of(3, 4)).forEach(appendNumbersTo(sb)); + assertEquals("1;2;3;4;", sb.toString()); + + sb.setLength(0); + LongStream.concat(LongStream.of(1, 2), LongStream.of(3, 4)).skip(1).forEach(appendNumbersTo(sb)); + assertEquals("2;3;4;", sb.toString()); + + sb.setLength(0); + LongStream.concat(LongStream.of(1, 2), LongStream.of(3, 4, 5)).skip(3).forEach(appendNumbersTo(sb)); + assertEquals("4;5;", sb.toString()); + } + + @Test + public void peekWorks() { + StringBuilder sb = new StringBuilder(); + LongStream.of(1, 2, 3).peek(appendNumbersTo(sb)).map(n -> n + 10).forEach(appendNumbersTo(sb)); + assertEquals("1;11;2;12;3;13;", sb.toString()); + } + + @Test + public void reduceWorks() { + assertEquals(10, LongStream.of(1, 2, 3, 4).reduce(0, (a, b) -> a + b)); + assertEquals(0, LongStream.of(1, 2, 3, 4).skip(4).reduce(0, (a, b) -> a + b)); + assertEquals(720, LongStream.iterate(1, n -> n + 1).limit(6).reduce(1, (a, b) -> a * b)); + + assertEquals(9, LongStream.of(1, 2, 3, 4).skip(1).reduce((a, b) -> a + b).getAsLong()); + assertFalse(LongStream.of(1, 2, 3, 4).skip(4).reduce((a, b) -> a + b).isPresent()); + } + + @Test + public void streamOfOneElement() { + StringBuilder sb = new StringBuilder(); + LongStream.of(5).forEach(appendNumbersTo(sb)); + assertEquals("5;", sb.toString()); + + sb.setLength(0); + LongStream.of(5).skip(1).forEach(appendNumbersTo(sb)); + assertEquals("", sb.toString()); + + sb.setLength(0); + LongStream.concat(LongStream.of(5), LongStream.of(6)).forEach(appendNumbersTo(sb)); + assertEquals("5;6;", sb.toString()); + } + + @Test + public void sortedStream() { + StringBuilder sb = new StringBuilder(); + LongStream.of(5, 7, 1, 2, 4, 3).sorted().forEach(appendNumbersTo(sb)); + assertEquals("1;2;3;4;5;7;", sb.toString()); + + sb.setLength(0); + LongStream.of(2, 3, 1).peek(appendNumbersTo(sb)).sorted().limit(2).map(n -> n + 10) + .forEach(appendNumbersTo(sb)); + assertEquals("2;3;1;11;12;", sb.toString()); + + sb.setLength(0); + LongStream.of(2, 3, 1).peek(appendNumbersTo(sb)).sorted().limit(0).forEach(appendNumbersTo(sb)); + assertEquals("2;3;1;", sb.toString()); + } + + @Test + public void minMax() { + assertEquals(3, LongStream.of(5, 7, 3, 6).min().getAsLong()); + assertEquals(7, LongStream.of(5, 7, 3, 6).max().getAsLong()); + + assertEquals(3, LongStream.of(5, 7, 3, 6).skip(1).min().getAsLong()); + assertEquals(7, LongStream.of(5, 7, 3, 6).skip(1).max().getAsLong()); + + assertEquals(3, LongStream.of(5, 7, 3, 6).skip(2).min().getAsLong()); + assertEquals(6, LongStream.of(5, 7, 3, 6).skip(2).max().getAsLong()); + + assertEquals(6, LongStream.of(5, 7, 3, 6).skip(3).min().getAsLong()); + assertEquals(6, LongStream.of(5, 7, 3, 6).skip(3).max().getAsLong()); + + assertFalse(LongStream.empty().min().isPresent()); + assertFalse(LongStream.empty().max().isPresent()); + } + + @Test + public void allNoneAny() { + assertTrue(LongStream.of(5, 7, 3, 6).anyMatch(n -> n == 7)); + assertFalse(LongStream.of(5, 7, 3, 6).anyMatch(n -> n == 11)); + assertFalse(LongStream.empty().anyMatch(n -> true)); + + assertFalse(LongStream.of(5, 7, 3, 6).noneMatch(n -> n == 7)); + assertTrue(LongStream.of(5, 7, 3, 6).noneMatch(n -> n == 11)); + assertTrue(LongStream.empty().noneMatch(n -> true)); + + assertTrue(LongStream.of(5, 7, 3, 6).allMatch(n -> n < 10)); + assertFalse(LongStream.of(5, 7, 3, 6).allMatch(n -> n < 6)); + assertTrue(LongStream.empty().allMatch(n -> false)); + } + + @Test + public void closeFlatMap() { + int[] closed = new int[3]; + + LongStream.of(0, 1) + .flatMap(n -> LongStream.of(n, n + 1).onClose(() -> closed[(int) n]++)) + .onClose(() -> closed[2]++) + .skip(10).close(); + + assertArrayEquals(new int[] { 0, 0, 1 }, closed); + } + + @Test + public void closeMap() { + int[] closed = new int[2]; + LongStream.of(1, 2).onClose(() -> closed[0]++).map(x -> x * 2).onClose(() -> closed[1]++).close(); + assertArrayEquals(new int[] { 1, 1 }, closed); + } + + @Test + public void closeConcat() { + int[] closed = new int[3]; + + LongStream.concat( + LongStream.of(1, 2).onClose(() -> closed[0]++), + LongStream.of(3, 4).onClose(() -> closed[1]++) + ).onClose(() -> closed[2]++).close(); + + assertArrayEquals(new int[] { 1, 1, 1 }, closed); + } + + @Test + public void iterator() { + StringBuilder sb = new StringBuilder(); + PrimitiveIterator.OfLong iterator = LongStream.of(1, 2, 3).iterator(); + while (iterator.hasNext()) { + sb.append(iterator.next()).append(';'); + } + assertEquals("1;2;3;", sb.toString()); + + sb.setLength(0); + iterator = LongStream.of(1, 2, 3).iterator(); + iterator.forEachRemaining(appendNumbersTo(sb)); + assertEquals("1;2;3;", sb.toString()); + } + + @Test + public void spliterator() { + StringBuilder sb = new StringBuilder(); + Spliterator.OfLong spliterator = LongStream.of(1, 2, 3).spliterator(); + while (spliterator.tryAdvance(appendNumbersTo(sb))) { + // continue + } + assertEquals("1;2;3;", sb.toString()); + + sb.setLength(0); + spliterator = LongStream.of(1, 2, 3).spliterator(); + spliterator.forEachRemaining(appendNumbersTo(sb)); + assertEquals("1;2;3;", sb.toString()); + } + + @Test + public void average() { + assertEquals(2.5, LongStream.of(1, 2, 3, 4).average().getAsDouble(), 0.001); + assertFalse(LongStream.empty().average().isPresent()); + } + + @Test + public void range() { + StringBuilder sb = new StringBuilder(); + LongStream.range(1, 4).forEach(appendNumbersTo(sb)); + assertEquals("1;2;3;", sb.toString()); + + sb.setLength(0); + LongStream.rangeClosed(1, 4).forEach(appendNumbersTo(sb)); + assertEquals("1;2;3;4;", sb.toString()); + } + + private LongConsumer appendNumbersTo(StringBuilder sb) { + return n -> sb.append(n).append(';'); + } + + private IntConsumer appendIntNumbersTo(StringBuilder sb) { + return n -> sb.append(n).append(';'); + } + + private DoubleConsumer appendDoubleNumbersTo(StringBuilder sb) { + return n -> sb.append(n).append(';'); + } +} diff --git a/tests/src/test/java/org/teavm/classlib/java/util/stream/StreamTest.java b/tests/src/test/java/org/teavm/classlib/java/util/stream/StreamTest.java new file mode 100644 index 000000000..9c41479f9 --- /dev/null +++ b/tests/src/test/java/org/teavm/classlib/java/util/stream/StreamTest.java @@ -0,0 +1,386 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.util.stream; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import java.util.Comparator; +import java.util.Iterator; +import java.util.Spliterator; +import java.util.function.Consumer; +import java.util.function.DoubleConsumer; +import java.util.function.Function; +import java.util.function.IntConsumer; +import java.util.function.LongConsumer; +import java.util.stream.DoubleStream; +import java.util.stream.IntStream; +import java.util.stream.LongStream; +import java.util.stream.Stream; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.teavm.junit.TeaVMTestRunner; + +@RunWith(TeaVMTestRunner.class) +public class StreamTest { + @Test + public void forEachWorks() { + StringBuilder sb = new StringBuilder(); + Stream.of(1, 2, 3).forEach(appendNumbersTo(sb)); + assertEquals("1;2;3;", sb.toString()); + } + + @Test + public void mapWorks() { + StringBuilder sb = new StringBuilder(); + Stream.of(1, 2, 3).map(n -> n * n).forEach(appendNumbersTo(sb)); + assertEquals("1;4;9;", sb.toString()); + } + + @Test + public void mapToIntWorks() { + StringBuilder sb = new StringBuilder(); + Stream.of(1, 2, 3).mapToInt(n -> n * n).forEach(appendIntNumbersTo(sb)); + assertEquals("1;4;9;", sb.toString()); + } + + @Test + public void mapToLongWorks() { + StringBuilder sb = new StringBuilder(); + Stream.of(1, 2, 3).mapToLong(n -> n * n).forEach(appendLongNumbersTo(sb)); + assertEquals("1;4;9;", sb.toString()); + } + + @Test + public void mapToDoubleWorks() { + StringBuilder sb = new StringBuilder(); + Stream.of(1, 2, 3).mapToDouble(n -> n * n).forEach(appendDoubleNumbersTo(sb)); + assertEquals("1.0;4.0;9.0;", sb.toString()); + } + + @Test + public void filterWorks() { + StringBuilder sb = new StringBuilder(); + Stream.of(1, 2, 3, 4, 5, 6).filter(n -> (n & 1) == 0).forEach(appendNumbersTo(sb)); + assertEquals("2;4;6;", sb.toString()); + } + + @Test + public void flatMapWorks() { + StringBuilder sb = new StringBuilder(); + Stream.of(Stream.of(1, 2), Stream.of(3, 4)).flatMap(n -> n).forEach(appendNumbersTo(sb)); + assertEquals("1;2;3;4;", sb.toString()); + + sb.setLength(0); + Stream.of(Stream.of(1, 2), Stream.of(3, 4)).flatMap(n -> n).skip(1).forEach(appendNumbersTo(sb)); + assertEquals("2;3;4;", sb.toString()); + + sb.setLength(0); + Stream.of(Stream.of(1, 2), Stream.of(3, 4, 5)).flatMap(n -> n).skip(3).forEach(appendNumbersTo(sb)); + assertEquals("4;5;", sb.toString()); + } + + @Test + public void flatMapToIntWorks() { + StringBuilder sb = new StringBuilder(); + Stream.of(IntStream.of(1, 2), IntStream.of(3, 4)).flatMapToInt(n -> n).forEach(appendIntNumbersTo(sb)); + assertEquals("1;2;3;4;", sb.toString()); + + sb.setLength(0); + Stream.of(IntStream.of(1, 2), IntStream.of(3, 4)).flatMapToInt(n -> n).skip(1).forEach(appendIntNumbersTo(sb)); + assertEquals("2;3;4;", sb.toString()); + + sb.setLength(0); + Stream.of(IntStream.of(1, 2), IntStream.of(3, 4, 5)).flatMapToInt(n -> n).skip(3) + .forEach(appendIntNumbersTo(sb)); + assertEquals("4;5;", sb.toString()); + } + + @Test + public void flatMapToLongWorks() { + StringBuilder sb = new StringBuilder(); + Stream.of(LongStream.of(1, 2), LongStream.of(3, 4)).flatMapToLong(n -> n).forEach(appendLongNumbersTo(sb)); + assertEquals("1;2;3;4;", sb.toString()); + + sb.setLength(0); + Stream.of(LongStream.of(1, 2), LongStream.of(3, 4)).flatMapToLong(n -> n).skip(1) + .forEach(appendLongNumbersTo(sb)); + assertEquals("2;3;4;", sb.toString()); + + sb.setLength(0); + Stream.of(LongStream.of(1, 2), LongStream.of(3, 4, 5)).flatMapToLong(n -> n).skip(3) + .forEach(appendLongNumbersTo(sb)); + assertEquals("4;5;", sb.toString()); + } + + @Test + public void flatMapToDoubleWorks() { + StringBuilder sb = new StringBuilder(); + Stream.of(DoubleStream.of(1, 2), DoubleStream.of(3, 4)).flatMapToDouble(n -> n) + .forEach(appendDoubleNumbersTo(sb)); + assertEquals("1.0;2.0;3.0;4.0;", sb.toString()); + + sb.setLength(0); + Stream.of(DoubleStream.of(1, 2), DoubleStream.of(3, 4)).flatMapToDouble(n -> n).skip(1) + .forEach(appendDoubleNumbersTo(sb)); + assertEquals("2.0;3.0;4.0;", sb.toString()); + + sb.setLength(0); + Stream.of(DoubleStream.of(1, 2), DoubleStream.of(3, 4, 5)).flatMapToDouble(n -> n).skip(3) + .forEach(appendDoubleNumbersTo(sb)); + assertEquals("4.0;5.0;", sb.toString()); + } + + @Test + public void skipWorks() { + for (int i = 0; i <= 6; ++i) { + StringBuilder sb = new StringBuilder(); + Stream.iterate(1, n -> n + 1).limit(5).skip(i).forEach(appendNumbersTo(sb)); + + StringBuilder expected = new StringBuilder(); + for (int j = i; j < 5; ++j) { + expected.append(j + 1).append(';'); + } + assertEquals("Error skipping " + i + " elements", expected.toString(), sb.toString()); + } + } + + @Test + public void limitWorks() { + for (int i = 0; i <= 3; ++i) { + StringBuilder sb = new StringBuilder(); + Stream.iterate(1, n -> n + 1).limit(i).forEach(appendNumbersTo(sb)); + + StringBuilder expected = new StringBuilder(); + for (int j = 0; j < i; ++j) { + expected.append(j + 1).append(';'); + } + assertEquals("Error limiting to " + i + " elements", expected.toString(), sb.toString()); + } + } + + @Test + public void countWorks() { + assertEquals(4, Stream.of(2, 3, 2, 3).count()); + assertEquals(3, Stream.of(2, 3, 2, 3).limit(3).count()); + assertEquals(4, Stream.of(2, 3, 2, 3).limit(5).count()); + assertEquals(0, Stream.of(2, 3, 2, 3).skip(5).count()); + assertEquals(3, Stream.of(2, 3, 2, 3).skip(1).count()); + + assertEquals(2, Stream.of(2, 3, 2, 3).filter(n -> n == 2).count()); + + assertEquals(10, Stream.generate(() -> 1).limit(10).count()); + assertEquals(10, Stream.generate(() -> 1).limit(10).count()); + + assertEquals(4, Stream.of(Stream.of(1, 2), Stream.of(3, 4)).flatMap(n -> n).count()); + } + + @Test + public void distinctWorks() { + assertArrayEquals(new Integer[] { 2, 3 }, Stream.of(2, 3, 2, 3).distinct().toArray(Integer[]::new)); + assertArrayEquals(new Integer[] { 3, 2 }, Stream.of(2, 3, 2, 3).skip(1).distinct().toArray(Integer[]::new)); + assertArrayEquals(new Integer[] { 2, 3 }, Stream.of(2, 3, 2, 3).limit(2).distinct().toArray(Integer[]::new)); + assertArrayEquals(new Integer[] { 2, 3, 4, 1 }, Stream.of(2, 2, 3, 2, 4, 3, 1).distinct() + .toArray(Integer[]::new)); + } + + @Test + public void findFirstWorks() { + assertEquals(2, Stream.of(2, 3).findFirst().get().intValue()); + assertEquals(3, Stream.of(2, 3).skip(1).findFirst().get().intValue()); + assertEquals(4, Stream.of(2, 3, 4, 5).filter(n -> n > 3).findFirst().get().intValue()); + assertFalse(Stream.of(2, 3, 4, 5).filter(n -> n > 10).findFirst().isPresent()); + assertFalse(Stream.of(2, 3).skip(3).findFirst().isPresent()); + assertEquals(20, Stream.of(2, 3).map(n -> n * 10).findFirst().get().intValue()); + } + + @Test + public void concatWorks() { + StringBuilder sb = new StringBuilder(); + Stream.concat(Stream.of(1, 2), Stream.of(3, 4)).forEach(appendNumbersTo(sb)); + assertEquals("1;2;3;4;", sb.toString()); + + sb.setLength(0); + Stream.concat(Stream.of(1, 2), Stream.of(3, 4)).skip(1).forEach(appendNumbersTo(sb)); + assertEquals("2;3;4;", sb.toString()); + + sb.setLength(0); + Stream.concat(Stream.of(1, 2), Stream.of(3, 4, 5)).skip(3).forEach(appendNumbersTo(sb)); + assertEquals("4;5;", sb.toString()); + } + + @Test + public void peekWorks() { + StringBuilder sb = new StringBuilder(); + Stream.of(1, 2, 3).peek(appendNumbersTo(sb)).map(n -> n + 10).forEach(appendNumbersTo(sb)); + assertEquals("1;11;2;12;3;13;", sb.toString()); + } + + @Test + public void reduceWorks() { + assertEquals(10, Stream.of(1, 2, 3, 4).reduce(0, (a, b) -> a + b).intValue()); + assertEquals(0, Stream.of(1, 2, 3, 4).skip(4).reduce(0, (a, b) -> a + b).intValue()); + assertEquals(720, Stream.iterate(1, n -> n + 1).limit(6).reduce(1, (a, b) -> a * b).intValue()); + + assertEquals(9, Stream.of(1, 2, 3, 4).skip(1).reduce((a, b) -> a + b).get().intValue()); + assertFalse(Stream.of(1, 2, 3, 4).skip(4).reduce((a, b) -> a + b).isPresent()); + } + + @Test + public void streamOfOneElement() { + StringBuilder sb = new StringBuilder(); + Stream.of(5).forEach(appendNumbersTo(sb)); + assertEquals("5;", sb.toString()); + + sb.setLength(0); + Stream.of(5).skip(1).forEach(appendNumbersTo(sb)); + assertEquals("", sb.toString()); + + sb.setLength(0); + Stream.concat(Stream.of(5), Stream.of(6)).forEach(appendNumbersTo(sb)); + assertEquals("5;6;", sb.toString()); + } + + @Test + public void sortedStream() { + StringBuilder sb = new StringBuilder(); + Stream.of(5, 7, 1, 2, 4, 3).sorted().forEach(appendNumbersTo(sb)); + assertEquals("1;2;3;4;5;7;", sb.toString()); + + sb.setLength(0); + Stream.of(2, 3, 1).peek(appendNumbersTo(sb)).sorted().limit(2).map(n -> n + 10).forEach(appendNumbersTo(sb)); + assertEquals("2;3;1;11;12;", sb.toString()); + + sb.setLength(0); + Stream.of(2, 3, 1).peek(appendNumbersTo(sb)).sorted().limit(0).forEach(appendNumbersTo(sb)); + assertEquals("2;3;1;", sb.toString()); + + sb.setLength(0); + Stream.of("qq", "aaa", "z").sorted(Comparator.comparing(x -> x.length())).forEach(s -> sb.append(s)); + assertEquals("zqqaaa", sb.toString()); + } + + @Test + public void minMax() { + assertEquals(3, Stream.of(5, 7, 3, 6).min(Comparator.comparing(x -> x)).get().intValue()); + assertEquals(7, Stream.of(5, 7, 3, 6).max(Comparator.comparing(x -> x)).get().intValue()); + + assertEquals(3, Stream.of(5, 7, 3, 6).skip(1).min(Comparator.comparing(x -> x)).get().intValue()); + assertEquals(7, Stream.of(5, 7, 3, 6).skip(1).max(Comparator.comparing(x -> x)).get().intValue()); + + assertEquals(3, Stream.of(5, 7, 3, 6).skip(2).min(Comparator.comparing(x -> x)).get().intValue()); + assertEquals(6, Stream.of(5, 7, 3, 6).skip(2).max(Comparator.comparing(x -> x)).get().intValue()); + + assertEquals(6, Stream.of(5, 7, 3, 6).skip(3).min(Comparator.comparing(x -> x)).get().intValue()); + assertEquals(6, Stream.of(5, 7, 3, 6).skip(3).max(Comparator.comparing(x -> x)).get().intValue()); + + assertFalse(Stream.empty().min(Comparator.comparing(x -> x)).isPresent()); + assertFalse(Stream.empty().max(Comparator.comparing(x -> x)).isPresent()); + } + + @Test + public void allNoneAny() { + assertTrue(Stream.of(5, 7, 3, 6).anyMatch(n -> n == 7)); + assertFalse(Stream.of(5, 7, 3, 6).anyMatch(n -> n == 11)); + assertFalse(Stream.empty().anyMatch(n -> true)); + + assertFalse(Stream.of(5, 7, 3, 6).noneMatch(n -> n == 7)); + assertTrue(Stream.of(5, 7, 3, 6).noneMatch(n -> n == 11)); + assertTrue(Stream.empty().noneMatch(n -> true)); + + assertTrue(Stream.of(5, 7, 3, 6).allMatch(n -> n < 10)); + assertFalse(Stream.of(5, 7, 3, 6).allMatch(n -> n < 6)); + assertTrue(Stream.empty().allMatch(n -> false)); + } + + @Test + public void closeFlatMap() { + int[] closed = new int[3]; + + Stream.of( + Stream.of(1, 2).onClose(() -> closed[0]++), + Stream.of(3, 4).onClose(() -> closed[1]++) + ).flatMap(Function.identity()).onClose(() -> closed[2]++).skip(10).close(); + + assertArrayEquals(new int[] { 0, 0, 1 }, closed); + } + + @Test + public void closeMap() { + int[] closed = new int[2]; + Stream.of(1, 2).onClose(() -> closed[0]++).map(x -> x * 2).onClose(() -> closed[1]++).close(); + assertArrayEquals(new int[] { 1, 1 }, closed); + } + + @Test + public void closeConcat() { + int[] closed = new int[3]; + + Stream.concat( + Stream.of(1, 2).onClose(() -> closed[0]++), + Stream.of(3, 4).onClose(() -> closed[1]++) + ).onClose(() -> closed[2]++).close(); + + assertArrayEquals(new int[] { 1, 1, 1 }, closed); + } + + @Test + public void iterator() { + StringBuilder sb = new StringBuilder(); + Iterator iterator = Stream.of(1, 2, 3).iterator(); + while (iterator.hasNext()) { + sb.append(iterator.next()).append(';'); + } + assertEquals("1;2;3;", sb.toString()); + + sb.setLength(0); + iterator = Stream.of(1, 2, 3).iterator(); + iterator.forEachRemaining(appendNumbersTo(sb)); + assertEquals("1;2;3;", sb.toString()); + } + + @Test + public void spliterator() { + StringBuilder sb = new StringBuilder(); + Spliterator spliterator = Stream.of(1, 2, 3).spliterator(); + while (spliterator.tryAdvance(appendNumbersTo(sb))) { + // continue + } + assertEquals("1;2;3;", sb.toString()); + + sb.setLength(0); + spliterator = Stream.of(1, 2, 3).spliterator(); + spliterator.forEachRemaining(appendNumbersTo(sb)); + assertEquals("1;2;3;", sb.toString()); + } + + private Consumer appendNumbersTo(StringBuilder sb) { + return n -> sb.append(n).append(';'); + } + + private IntConsumer appendIntNumbersTo(StringBuilder sb) { + return n -> sb.append(n).append(';'); + } + + private LongConsumer appendLongNumbersTo(StringBuilder sb) { + return n -> sb.append(n).append(';'); + } + + private DoubleConsumer appendDoubleNumbersTo(StringBuilder sb) { + return n -> sb.append(n).append(';'); + } +}