Refactor stream implementation and tests, fix some bugs

This commit is contained in:
Alexey Andreev 2019-11-08 19:30:10 +03:00
parent 74ee848e0c
commit b090c2f47d
44 changed files with 1342 additions and 697 deletions

View File

@ -0,0 +1,35 @@
/*
* Copyright 2019 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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 TAllMatchConsumer implements DoublePredicate {
public boolean matched = true;
private DoublePredicate predicate;
public TAllMatchConsumer(DoublePredicate predicate) {
this.predicate = predicate;
}
@Override
public boolean test(double t) {
if (!predicate.test(t)) {
matched = false;
}
return matched;
}
}

View File

@ -0,0 +1,33 @@
/*
* Copyright 2019 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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 TAnyMatchConsumer implements DoublePredicate {
public boolean matched;
private DoublePredicate predicate;
public TAnyMatchConsumer(DoublePredicate predicate) {
this.predicate = predicate;
}
@Override
public boolean test(double t) {
matched = predicate.test(t);
return !matched;
}
}

View File

@ -30,6 +30,6 @@ public class TEmptyDoubleStreamImpl extends TSimpleDoubleStreamImpl {
@Override @Override
public long count() { public long count() {
return 1; return 0;
} }
} }

View File

@ -22,6 +22,7 @@ import org.teavm.classlib.java.util.stream.TDoubleStream;
public class TFlatMappingDoubleStreamImpl extends TSimpleDoubleStreamImpl { public class TFlatMappingDoubleStreamImpl extends TSimpleDoubleStreamImpl {
private TSimpleDoubleStreamImpl sourceStream; private TSimpleDoubleStreamImpl sourceStream;
private boolean currentSet;
private TDoubleStream current; private TDoubleStream current;
private PrimitiveIterator.OfDouble iterator; private PrimitiveIterator.OfDouble iterator;
private DoubleFunction<? extends TDoubleStream> mapper; private DoubleFunction<? extends TDoubleStream> mapper;
@ -35,42 +36,44 @@ public class TFlatMappingDoubleStreamImpl extends TSimpleDoubleStreamImpl {
@Override @Override
public boolean next(DoublePredicate consumer) { public boolean next(DoublePredicate consumer) {
while (true) { if (current == null) {
if (current == null) { if (done) {
if (done) { return false;
return false; }
} currentSet = false;
while (!currentSet) {
boolean hasMore = sourceStream.next(e -> { boolean hasMore = sourceStream.next(e -> {
current = mapper.apply(e); current = mapper.apply(e);
currentSet = true;
return false; return false;
}); });
if (!hasMore) { if (!hasMore) {
done = true; done = true;
} break;
if (current == null) {
done = true;
return false;
} }
} }
if (current instanceof TSimpleDoubleStreamImpl) { if (current == null) {
@SuppressWarnings("unchecked") return false;
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;
} }
} }
if (current instanceof TSimpleDoubleStreamImpl) {
TSimpleDoubleStreamImpl castCurrent = (TSimpleDoubleStreamImpl) current;
if (castCurrent.next(consumer)) {
return true;
}
current = null;
} else {
iterator = current.iterator();
while (iterator.hasNext()) {
double e = iterator.next();
if (!consumer.test(e)) {
return true;
}
}
iterator = null;
current = null;
}
return true;
} }
@Override @Override

View File

@ -101,10 +101,15 @@ public abstract class TSimpleDoubleStreamImpl implements TDoubleStream {
@Override @Override
public void forEachOrdered(DoubleConsumer action) { public void forEachOrdered(DoubleConsumer action) {
next(e -> { while (true) {
action.accept(e); boolean hasMore = next(e -> {
return true; action.accept(e);
}); return true;
});
if (!hasMore) {
return;
}
}
} }
@Override @Override
@ -112,7 +117,9 @@ public abstract class TSimpleDoubleStreamImpl implements TDoubleStream {
int estimatedSize = estimateSize(); int estimatedSize = estimateSize();
if (estimatedSize < 0) { if (estimatedSize < 0) {
List<Double> list = new ArrayList<>(); List<Double> list = new ArrayList<>();
next(list::add); while (next(list::add)) {
// go on
}
double[] array = new double[list.size()]; double[] array = new double[list.size()];
for (int i = 0; i < array.length; ++i) { for (int i = 0; i < array.length; ++i) {
array[i] = list.get(i); array[i] = list.get(i);
@ -121,8 +128,9 @@ public abstract class TSimpleDoubleStreamImpl implements TDoubleStream {
} else { } else {
double[] array = new double[estimatedSize]; double[] array = new double[estimatedSize];
ArrayFillingConsumer consumer = new ArrayFillingConsumer(array); ArrayFillingConsumer consumer = new ArrayFillingConsumer(array);
boolean wantsMore = next(consumer); while (next(consumer)) {
assert !wantsMore : "next() should have reported done status"; // go on
}
if (consumer.index < array.length) { if (consumer.index < array.length) {
array = Arrays.copyOf(array, consumer.index); array = Arrays.copyOf(array, consumer.index);
} }
@ -133,26 +141,33 @@ public abstract class TSimpleDoubleStreamImpl implements TDoubleStream {
@Override @Override
public double reduce(double identity, DoubleBinaryOperator accumulator) { public double reduce(double identity, DoubleBinaryOperator accumulator) {
TReducingDoubleConsumer consumer = new TReducingDoubleConsumer(accumulator, identity, true); TReducingDoubleConsumer consumer = new TReducingDoubleConsumer(accumulator, identity, true);
boolean wantsMore = next(consumer); while (next(consumer)) {
assert !wantsMore : "next() should have returned true"; // go on
}
return consumer.result; return consumer.result;
} }
@Override @Override
public OptionalDouble reduce(DoubleBinaryOperator accumulator) { public OptionalDouble reduce(DoubleBinaryOperator accumulator) {
TReducingDoubleConsumer consumer = new TReducingDoubleConsumer(accumulator, 0, false); TReducingDoubleConsumer consumer = new TReducingDoubleConsumer(accumulator, 0, false);
boolean wantsMore = next(consumer); while (next(consumer)) {
assert !wantsMore : "next() should have returned true"; // go on
}
return consumer.initialized ? OptionalDouble.of(consumer.result) : OptionalDouble.empty(); return consumer.initialized ? OptionalDouble.of(consumer.result) : OptionalDouble.empty();
} }
@Override @Override
public <R> R collect(Supplier<R> supplier, ObjDoubleConsumer<R> accumulator, BiConsumer<R, R> combiner) { public <R> R collect(Supplier<R> supplier, ObjDoubleConsumer<R> accumulator, BiConsumer<R, R> combiner) {
R collection = supplier.get(); R collection = supplier.get();
next(e -> { while (true) {
accumulator.accept(collection, e); boolean hasMore = next(e -> {
return true; accumulator.accept(collection, e);
}); return true;
});
if (!hasMore) {
break;
}
}
return collection; return collection;
} }
@ -169,32 +184,46 @@ public abstract class TSimpleDoubleStreamImpl implements TDoubleStream {
@Override @Override
public long count() { public long count() {
TCountingDoubleConsumer consumer = new TCountingDoubleConsumer(); TCountingDoubleConsumer consumer = new TCountingDoubleConsumer();
next(consumer); while (next(consumer)) {
// go on
}
return consumer.count; return consumer.count;
} }
@Override @Override
public double sum() { public double sum() {
TSumDoubleConsumer consumer = new TSumDoubleConsumer(); TSumDoubleConsumer consumer = new TSumDoubleConsumer();
next(consumer); while (next(consumer)) {
// go on
}
return consumer.sum; return consumer.sum;
} }
@Override @Override
public OptionalDouble average() { public OptionalDouble average() {
TAverageDoubleConsumer consumer = new TAverageDoubleConsumer(); TAverageDoubleConsumer consumer = new TAverageDoubleConsumer();
next(consumer); while (next(consumer)) {
// go on
}
return consumer.count > 0 ? OptionalDouble.of(consumer.sum / consumer.count) : OptionalDouble.empty(); return consumer.count > 0 ? OptionalDouble.of(consumer.sum / consumer.count) : OptionalDouble.empty();
} }
@Override @Override
public boolean anyMatch(DoublePredicate predicate) { public boolean anyMatch(DoublePredicate predicate) {
return next(predicate.negate()); TAnyMatchConsumer consumer = new TAnyMatchConsumer(predicate);
while (!consumer.matched && next(consumer)) {
// go on
}
return consumer.matched;
} }
@Override @Override
public boolean allMatch(DoublePredicate predicate) { public boolean allMatch(DoublePredicate predicate) {
return !next(predicate); TAllMatchConsumer consumer = new TAllMatchConsumer(predicate);
while (consumer.matched && next(consumer)) {
// go on
}
return consumer.matched;
} }
@Override @Override
@ -205,7 +234,9 @@ public abstract class TSimpleDoubleStreamImpl implements TDoubleStream {
@Override @Override
public OptionalDouble findFirst() { public OptionalDouble findFirst() {
TFindFirstDoubleConsumer consumer = new TFindFirstDoubleConsumer(); TFindFirstDoubleConsumer consumer = new TFindFirstDoubleConsumer();
next(consumer); while (!consumer.hasAny && next(consumer)) {
// go on
}
return consumer.hasAny ? OptionalDouble.of(consumer.result) : OptionalDouble.empty(); return consumer.hasAny ? OptionalDouble.of(consumer.result) : OptionalDouble.empty();
} }
@ -264,7 +295,7 @@ public abstract class TSimpleDoubleStreamImpl implements TDoubleStream {
public abstract boolean next(DoublePredicate consumer); public abstract boolean next(DoublePredicate consumer);
class ArrayFillingConsumer implements DoublePredicate { static class ArrayFillingConsumer implements DoublePredicate {
double[] array; double[] array;
int index; int index;

View File

@ -53,13 +53,21 @@ public class TSimpleDoubleStreamIterator implements PrimitiveIterator.OfDouble {
if (state != NEEDS_MORE) { if (state != NEEDS_MORE) {
return; return;
} }
boolean hasMore = stream.next(e -> { state = NEEDS_MORE;
lastElement = e; while (state == NEEDS_MORE) {
return false; boolean hasMore = stream.next(e -> {
}); lastElement = e;
state = hasMore ? HAS_DATA : LAST_ELEMENT; state = HAS_DATA;
if (state == LAST_ELEMENT) { return false;
stream = null; });
if (!hasMore) {
if (state == NEEDS_MORE) {
state = DONE;
} else {
state = LAST_ELEMENT;
}
stream = null;
}
} }
} }
} }

View File

@ -20,6 +20,7 @@ import java.util.function.DoubleConsumer;
public class TSimpleDoubleStreamSpliterator implements Spliterator.OfDouble { public class TSimpleDoubleStreamSpliterator implements Spliterator.OfDouble {
private TSimpleDoubleStreamImpl stream; private TSimpleDoubleStreamImpl stream;
private boolean foundItems;
private boolean done; private boolean done;
public TSimpleDoubleStreamSpliterator(TSimpleDoubleStreamImpl stream) { public TSimpleDoubleStreamSpliterator(TSimpleDoubleStreamImpl stream) {
@ -39,10 +40,14 @@ public class TSimpleDoubleStreamSpliterator implements Spliterator.OfDouble {
if (done) { if (done) {
return false; return false;
} }
done = !stream.next(x -> { foundItems = false;
action.accept(x); while (!foundItems && !done) {
return false; done = !stream.next(x -> {
}); action.accept(x);
foundItems = true;
return false;
});
}
return true; return true;
} }

View File

@ -30,7 +30,7 @@ public class TSkippingDoubleStreamImpl extends TSimpleDoubleStreamImpl {
@Override @Override
public boolean next(DoublePredicate consumer) { public boolean next(DoublePredicate consumer) {
if (remaining > 0) { while (remaining > 0) {
if (!sourceStream.next(e -> --remaining > 0)) { if (!sourceStream.next(e -> --remaining > 0)) {
return false; return false;
} }

View File

@ -33,16 +33,15 @@ public class TSpecializedConcatDoubleStream extends TSimpleDoubleStreamImpl {
if (current == null) { if (current == null) {
return false; return false;
} }
while (true) { if (current.next(consumer)) {
if (current.next(consumer)) { return true;
return true; }
} if (current == first) {
if (current == first) { current = second;
current = second; return true;
} else { } else {
current = null; current = null;
return false; return false;
}
} }
} }

View File

@ -0,0 +1,35 @@
/*
* Copyright 2019 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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 TAllMatchConsumer<T> implements Predicate<T> {
public boolean matched = true;
private Predicate<? super T> predicate;
public TAllMatchConsumer(Predicate<? super T> predicate) {
this.predicate = predicate;
}
@Override
public boolean test(T t) {
if (!predicate.test(t)) {
matched = false;
}
return matched;
}
}

View File

@ -0,0 +1,33 @@
/*
* Copyright 2019 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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 TAnyMatchConsumer<T> implements Predicate<T> {
public boolean matched;
private Predicate<? super T> predicate;
public TAnyMatchConsumer(Predicate<? super T> predicate) {
this.predicate = predicate;
}
@Override
public boolean test(T t) {
matched = predicate.test(t);
return !matched;
}
}

View File

@ -30,6 +30,6 @@ public class TEmptyStreamImpl<T> extends TSimpleStreamImpl<T> {
@Override @Override
public long count() { public long count() {
return 1; return 0;
} }
} }

View File

@ -22,6 +22,7 @@ import org.teavm.classlib.java.util.stream.TStream;
public class TFlatMappingStreamImpl<T, S> extends TSimpleStreamImpl<T> { public class TFlatMappingStreamImpl<T, S> extends TSimpleStreamImpl<T> {
private TSimpleStreamImpl<S> sourceStream; private TSimpleStreamImpl<S> sourceStream;
private boolean currentSet;
private TStream<? extends T> current; private TStream<? extends T> current;
private Iterator<? extends T> iterator; private Iterator<? extends T> iterator;
private Function<? super S, ? extends TStream<? extends T>> mapper; private Function<? super S, ? extends TStream<? extends T>> mapper;
@ -35,42 +36,45 @@ public class TFlatMappingStreamImpl<T, S> extends TSimpleStreamImpl<T> {
@Override @Override
public boolean next(Predicate<? super T> consumer) { public boolean next(Predicate<? super T> consumer) {
while (true) { if (current == null) {
if (current == null) { if (done) {
if (done) { return false;
return false; }
} currentSet = false;
while (!currentSet) {
boolean hasMore = sourceStream.next(e -> { boolean hasMore = sourceStream.next(e -> {
current = mapper.apply(e); current = mapper.apply(e);
currentSet = true;
return false; return false;
}); });
if (!hasMore) { if (!hasMore) {
done = true; done = true;
} break;
if (current == null) {
done = true;
return false;
} }
} }
if (current instanceof TSimpleStreamImpl) { if (current == null) {
@SuppressWarnings("unchecked") return false;
TSimpleStreamImpl<? extends T> castCurrent = (TSimpleStreamImpl<? extends T>) 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;
} }
} }
if (current instanceof TSimpleStreamImpl) {
@SuppressWarnings("unchecked")
TSimpleStreamImpl<? extends T> castCurrent = (TSimpleStreamImpl<? extends T>) 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;
}
return true;
} }
@Override @Override

View File

@ -24,6 +24,7 @@ import org.teavm.classlib.java.util.stream.doubleimpl.TSimpleDoubleStreamImpl;
public class TFlatMappingToDoubleStreamImpl<T> extends TSimpleDoubleStreamImpl { public class TFlatMappingToDoubleStreamImpl<T> extends TSimpleDoubleStreamImpl {
private TSimpleStreamImpl<T> sourceStream; private TSimpleStreamImpl<T> sourceStream;
private TDoubleStream current; private TDoubleStream current;
private boolean currentSet;
private PrimitiveIterator.OfDouble iterator; private PrimitiveIterator.OfDouble iterator;
private Function<? super T, ? extends TDoubleStream> mapper; private Function<? super T, ? extends TDoubleStream> mapper;
private boolean done; private boolean done;
@ -36,42 +37,44 @@ public class TFlatMappingToDoubleStreamImpl<T> extends TSimpleDoubleStreamImpl {
@Override @Override
public boolean next(DoublePredicate consumer) { public boolean next(DoublePredicate consumer) {
while (true) { if (current == null) {
if (current == null) { if (done) {
if (done) { return false;
return false; }
} currentSet = false;
while (!currentSet) {
boolean hasMore = sourceStream.next(e -> { boolean hasMore = sourceStream.next(e -> {
current = mapper.apply(e); current = mapper.apply(e);
currentSet = true;
return false; return false;
}); });
if (!hasMore) { if (!hasMore) {
done = true; done = true;
} break;
if (current == null) {
done = true;
return false;
} }
} }
if (current instanceof TSimpleDoubleStreamImpl) { if (current == null) {
@SuppressWarnings("unchecked") return false;
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;
} }
} }
if (current instanceof TSimpleDoubleStreamImpl) {
TSimpleDoubleStreamImpl castCurrent = (TSimpleDoubleStreamImpl) current;
if (castCurrent.next(consumer)) {
return true;
}
current = null;
} else {
iterator = current.iterator();
while (iterator.hasNext()) {
double e = iterator.next();
if (!consumer.test(e)) {
return true;
}
}
iterator = null;
current = null;
}
return true;
} }
@Override @Override

View File

@ -24,6 +24,7 @@ import org.teavm.classlib.java.util.stream.intimpl.TSimpleIntStreamImpl;
public class TFlatMappingToIntStreamImpl<T> extends TSimpleIntStreamImpl { public class TFlatMappingToIntStreamImpl<T> extends TSimpleIntStreamImpl {
private TSimpleStreamImpl<T> sourceStream; private TSimpleStreamImpl<T> sourceStream;
private TIntStream current; private TIntStream current;
private boolean currentSet;
private PrimitiveIterator.OfInt iterator; private PrimitiveIterator.OfInt iterator;
private Function<? super T, ? extends TIntStream> mapper; private Function<? super T, ? extends TIntStream> mapper;
private boolean done; private boolean done;
@ -36,42 +37,44 @@ public class TFlatMappingToIntStreamImpl<T> extends TSimpleIntStreamImpl {
@Override @Override
public boolean next(IntPredicate consumer) { public boolean next(IntPredicate consumer) {
while (true) { if (current == null) {
if (current == null) { if (done) {
if (done) { return false;
return false; }
} currentSet = false;
while (!currentSet) {
boolean hasMore = sourceStream.next(e -> { boolean hasMore = sourceStream.next(e -> {
current = mapper.apply(e); current = mapper.apply(e);
currentSet = true;
return false; return false;
}); });
if (!hasMore) { if (!hasMore) {
done = true; done = true;
} break;
if (current == null) {
done = true;
return false;
} }
} }
if (current instanceof TSimpleIntStreamImpl) { if (current == null) {
@SuppressWarnings("unchecked") return false;
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;
} }
} }
if (current instanceof TSimpleIntStreamImpl) {
TSimpleIntStreamImpl castCurrent = (TSimpleIntStreamImpl) current;
if (castCurrent.next(consumer)) {
return true;
}
current = null;
} else {
iterator = current.iterator();
while (iterator.hasNext()) {
int e = iterator.next();
if (!consumer.test(e)) {
return true;
}
}
iterator = null;
current = null;
}
return true;
} }
@Override @Override

View File

@ -24,6 +24,7 @@ import org.teavm.classlib.java.util.stream.longimpl.TSimpleLongStreamImpl;
public class TFlatMappingToLongStreamImpl<T> extends TSimpleLongStreamImpl { public class TFlatMappingToLongStreamImpl<T> extends TSimpleLongStreamImpl {
private TSimpleStreamImpl<T> sourceStream; private TSimpleStreamImpl<T> sourceStream;
private TLongStream current; private TLongStream current;
private boolean currentSet;
private PrimitiveIterator.OfLong iterator; private PrimitiveIterator.OfLong iterator;
private Function<? super T, ? extends TLongStream> mapper; private Function<? super T, ? extends TLongStream> mapper;
private boolean done; private boolean done;
@ -36,42 +37,44 @@ public class TFlatMappingToLongStreamImpl<T> extends TSimpleLongStreamImpl {
@Override @Override
public boolean next(LongPredicate consumer) { public boolean next(LongPredicate consumer) {
while (true) { if (current == null) {
if (current == null) { if (done) {
if (done) { return false;
return false; }
} currentSet = false;
while (!currentSet) {
boolean hasMore = sourceStream.next(e -> { boolean hasMore = sourceStream.next(e -> {
current = mapper.apply(e); current = mapper.apply(e);
currentSet = true;
return false; return false;
}); });
if (!hasMore) { if (!hasMore) {
done = true; done = true;
} break;
if (current == null) {
done = true;
return false;
} }
} }
if (current instanceof TSimpleLongStreamImpl) { if (current == null) {
@SuppressWarnings("unchecked") return false;
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;
} }
} }
if (current instanceof TSimpleLongStreamImpl) {
TSimpleLongStreamImpl castCurrent = (TSimpleLongStreamImpl) current;
if (castCurrent.next(consumer)) {
return true;
}
current = null;
} else {
iterator = current.iterator();
while (iterator.hasNext()) {
long e = iterator.next();
if (!consumer.test(e)) {
return true;
}
}
iterator = null;
current = null;
}
return true;
} }
@Override @Override

View File

@ -123,10 +123,15 @@ public abstract class TSimpleStreamImpl<T> implements TStream<T> {
@Override @Override
public void forEachOrdered(Consumer<? super T> action) { public void forEachOrdered(Consumer<? super T> action) {
next(e -> { while (true) {
action.accept(e); boolean hasMore = next(e -> {
return true; action.accept(e);
}); return true;
});
if (!hasMore) {
return;
}
}
} }
@Override @Override
@ -140,7 +145,9 @@ public abstract class TSimpleStreamImpl<T> implements TStream<T> {
int estimatedSize = estimateSize(); int estimatedSize = estimateSize();
if (estimatedSize < 0) { if (estimatedSize < 0) {
List<T> list = new ArrayList<>(); List<T> list = new ArrayList<>();
next(list::add); while (next(list::add)) {
// go on
}
A[] array = generator.apply(list.size()); A[] array = generator.apply(list.size());
for (int i = 0; i < array.length; ++i) { for (int i = 0; i < array.length; ++i) {
array[i] = (A) list.get(i); array[i] = (A) list.get(i);
@ -148,9 +155,10 @@ public abstract class TSimpleStreamImpl<T> implements TStream<T> {
return array; return array;
} else { } else {
A[] array = generator.apply(estimatedSize); A[] array = generator.apply(estimatedSize);
ArrayFillingConsumer<A> consumer = new ArrayFillingConsumer<>(array); ArrayFillingConsumer<A, T> consumer = new ArrayFillingConsumer<>(array);
boolean wantsMore = next(consumer); while (next(consumer)) {
assert !wantsMore : "next() should have reported done status"; // go on
}
if (consumer.index < array.length) { if (consumer.index < array.length) {
array = Arrays.copyOf(array, consumer.index); array = Arrays.copyOf(array, consumer.index);
} }
@ -161,34 +169,42 @@ public abstract class TSimpleStreamImpl<T> implements TStream<T> {
@Override @Override
public T reduce(T identity, BinaryOperator<T> accumulator) { public T reduce(T identity, BinaryOperator<T> accumulator) {
TReducingConsumer<T> consumer = new TReducingConsumer<>(accumulator, identity, true); TReducingConsumer<T> consumer = new TReducingConsumer<>(accumulator, identity, true);
boolean wantsMore = next(consumer); while (next(consumer)) {
assert !wantsMore : "next() should have returned true"; // go on
}
return consumer.result; return consumer.result;
} }
@Override @Override
public Optional<T> reduce(BinaryOperator<T> accumulator) { public Optional<T> reduce(BinaryOperator<T> accumulator) {
TReducingConsumer<T> consumer = new TReducingConsumer<>(accumulator, null, false); TReducingConsumer<T> consumer = new TReducingConsumer<>(accumulator, null, false);
boolean wantsMore = next(consumer); while (next(consumer)) {
assert !wantsMore : "next() should have returned true"; // go on
}
return Optional.ofNullable(consumer.result); return Optional.ofNullable(consumer.result);
} }
@Override @Override
public <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner) { public <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner) {
TReducingConsumer2<T, U> consumer = new TReducingConsumer2<>(accumulator, identity); TReducingConsumer2<T, U> consumer = new TReducingConsumer2<>(accumulator, identity);
boolean wantsMore = next(consumer); while (next(consumer)) {
assert !wantsMore : "next() should have returned true"; // go on
}
return consumer.result; return consumer.result;
} }
@Override @Override
public <R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner) { public <R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner) {
R collection = supplier.get(); R collection = supplier.get();
next(e -> { while (true) {
accumulator.accept(collection, e); boolean hasMore = next(e -> {
return true; accumulator.accept(collection, e);
}); return true;
});
if (!hasMore) {
break;
}
}
return collection; return collection;
} }
@ -216,18 +232,28 @@ public abstract class TSimpleStreamImpl<T> implements TStream<T> {
@Override @Override
public long count() { public long count() {
TCountingConsumer<T> consumer = new TCountingConsumer<>(); TCountingConsumer<T> consumer = new TCountingConsumer<>();
next(consumer); while (next(consumer)) {
// go on
}
return consumer.count; return consumer.count;
} }
@Override @Override
public boolean anyMatch(Predicate<? super T> predicate) { public boolean anyMatch(Predicate<? super T> predicate) {
return next(predicate.negate()); TAnyMatchConsumer<T> consumer = new TAnyMatchConsumer<>(predicate);
while (!consumer.matched && next(consumer)) {
// go on
}
return consumer.matched;
} }
@Override @Override
public boolean allMatch(Predicate<? super T> predicate) { public boolean allMatch(Predicate<? super T> predicate) {
return !next(predicate); TAllMatchConsumer<T> consumer = new TAllMatchConsumer<>(predicate);
while (consumer.matched && next(consumer)) {
// go on
}
return consumer.matched;
} }
@Override @Override
@ -238,7 +264,9 @@ public abstract class TSimpleStreamImpl<T> implements TStream<T> {
@Override @Override
public Optional<T> findFirst() { public Optional<T> findFirst() {
TFindFirstConsumer<T> consumer = new TFindFirstConsumer<>(); TFindFirstConsumer<T> consumer = new TFindFirstConsumer<>();
next(consumer); while (consumer.result == null && next(consumer)) {
// go on
}
return Optional.ofNullable(consumer.result); return Optional.ofNullable(consumer.result);
} }
@ -292,7 +320,7 @@ public abstract class TSimpleStreamImpl<T> implements TStream<T> {
public abstract boolean next(Predicate<? super T> consumer); public abstract boolean next(Predicate<? super T> consumer);
class ArrayFillingConsumer<A> implements Predicate<T> { static class ArrayFillingConsumer<A, T> implements Predicate<T> {
A[] array; A[] array;
int index; int index;

View File

@ -63,13 +63,21 @@ public class TSimpleStreamIterator<T> implements Iterator<T> {
if (state != NEEDS_MORE) { if (state != NEEDS_MORE) {
return; return;
} }
boolean hasMore = stream.next(e -> { state = NEEDS_MORE;
lastElement = e; while (state == NEEDS_MORE) {
return false; boolean hasMore = stream.next(e -> {
}); lastElement = e;
state = hasMore ? HAS_DATA : LAST_ELEMENT; state = HAS_DATA;
if (state == LAST_ELEMENT) { return false;
stream = null; });
if (!hasMore) {
if (state == NEEDS_MORE) {
state = DONE;
} else {
state = LAST_ELEMENT;
}
stream = null;
}
} }
} }
} }

View File

@ -20,6 +20,7 @@ import java.util.function.Consumer;
public class TSimpleStreamSpliterator<T> implements Spliterator<T> { public class TSimpleStreamSpliterator<T> implements Spliterator<T> {
private TSimpleStreamImpl<T> stream; private TSimpleStreamImpl<T> stream;
private boolean foundItems;
private boolean done; private boolean done;
public TSimpleStreamSpliterator(TSimpleStreamImpl<T> stream) { public TSimpleStreamSpliterator(TSimpleStreamImpl<T> stream) {
@ -28,10 +29,15 @@ public class TSimpleStreamSpliterator<T> implements Spliterator<T> {
@Override @Override
public void forEachRemaining(Consumer<? super T> action) { public void forEachRemaining(Consumer<? super T> action) {
stream.next(x -> { while (true) {
action.accept(x); boolean hasMore = stream.next(x -> {
return true; action.accept(x);
}); return true;
});
if (!hasMore) {
break;
}
}
} }
@Override @Override
@ -39,10 +45,14 @@ public class TSimpleStreamSpliterator<T> implements Spliterator<T> {
if (done) { if (done) {
return false; return false;
} }
done = !stream.next(x -> { foundItems = false;
action.accept(x); while (!foundItems && !done) {
return false; done = !stream.next(x -> {
}); action.accept(x);
foundItems = true;
return false;
});
}
return true; return true;
} }

View File

@ -30,7 +30,7 @@ public class TSkippingStreamImpl<T> extends TSimpleStreamImpl<T> {
@Override @Override
public boolean next(Predicate<? super T> consumer) { public boolean next(Predicate<? super T> consumer) {
if (remaining > 0) { while (remaining > 0) {
if (!sourceStream.next(e -> --remaining > 0)) { if (!sourceStream.next(e -> --remaining > 0)) {
return false; return false;
} }

View File

@ -33,16 +33,15 @@ public class TSpecializedConcatStream<T> extends TSimpleStreamImpl<T> {
if (current == null) { if (current == null) {
return false; return false;
} }
while (true) { if (current.next(consumer)) {
if (current.next(consumer)) { return true;
return true; }
} if (current == first) {
if (current == first) { current = second;
current = second; return true;
} else { } else {
current = null; current = null;
return false; return false;
}
} }
} }

View File

@ -0,0 +1,35 @@
/*
* Copyright 2019 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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 TAllMatchConsumer implements IntPredicate {
public boolean matched = true;
private IntPredicate predicate;
public TAllMatchConsumer(IntPredicate predicate) {
this.predicate = predicate;
}
@Override
public boolean test(int t) {
if (!predicate.test(t)) {
matched = false;
}
return matched;
}
}

View File

@ -0,0 +1,33 @@
/*
* Copyright 2019 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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 TAnyMatchConsumer implements IntPredicate {
public boolean matched;
private IntPredicate predicate;
public TAnyMatchConsumer(IntPredicate predicate) {
this.predicate = predicate;
}
@Override
public boolean test(int t) {
matched = predicate.test(t);
return !matched;
}
}

View File

@ -30,6 +30,6 @@ public class TEmptyIntStreamImpl extends TSimpleIntStreamImpl {
@Override @Override
public long count() { public long count() {
return 1; return 0;
} }
} }

View File

@ -22,6 +22,7 @@ import org.teavm.classlib.java.util.stream.TIntStream;
public class TFlatMappingIntStreamImpl extends TSimpleIntStreamImpl { public class TFlatMappingIntStreamImpl extends TSimpleIntStreamImpl {
private TSimpleIntStreamImpl sourceStream; private TSimpleIntStreamImpl sourceStream;
private boolean currentSet;
private TIntStream current; private TIntStream current;
private PrimitiveIterator.OfInt iterator; private PrimitiveIterator.OfInt iterator;
private IntFunction<? extends TIntStream> mapper; private IntFunction<? extends TIntStream> mapper;
@ -34,42 +35,44 @@ public class TFlatMappingIntStreamImpl extends TSimpleIntStreamImpl {
@Override @Override
public boolean next(IntPredicate consumer) { public boolean next(IntPredicate consumer) {
while (true) { if (current == null) {
if (current == null) { if (done) {
if (done) { return false;
return false; }
} currentSet = false;
while (!currentSet) {
boolean hasMore = sourceStream.next(e -> { boolean hasMore = sourceStream.next(e -> {
current = mapper.apply(e); current = mapper.apply(e);
currentSet = true;
return false; return false;
}); });
if (!hasMore) { if (!hasMore) {
done = true; done = true;
} break;
if (current == null) {
done = true;
return false;
} }
} }
if (current instanceof TSimpleIntStreamImpl) { if (current == null) {
@SuppressWarnings("unchecked") return false;
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;
} }
} }
if (current instanceof TSimpleIntStreamImpl) {
TSimpleIntStreamImpl castCurrent = (TSimpleIntStreamImpl) current;
if (castCurrent.next(consumer)) {
return true;
}
current = null;
} else {
iterator = current.iterator();
while (iterator.hasNext()) {
int e = iterator.next();
if (!consumer.test(e)) {
return true;
}
}
iterator = null;
current = null;
}
return true;
} }
@Override @Override

View File

@ -102,10 +102,15 @@ public abstract class TSimpleIntStreamImpl implements TIntStream {
@Override @Override
public void forEachOrdered(IntConsumer action) { public void forEachOrdered(IntConsumer action) {
next(e -> { while (true) {
action.accept(e); boolean hasMore = next(e -> {
return true; action.accept(e);
}); return true;
});
if (!hasMore) {
return;
}
}
} }
@Override @Override
@ -113,7 +118,9 @@ public abstract class TSimpleIntStreamImpl implements TIntStream {
int estimatedSize = estimateSize(); int estimatedSize = estimateSize();
if (estimatedSize < 0) { if (estimatedSize < 0) {
List<Integer> list = new ArrayList<>(); List<Integer> list = new ArrayList<>();
next(list::add); while (next(list::add)) {
// go on
}
int[] array = new int[list.size()]; int[] array = new int[list.size()];
for (int i = 0; i < array.length; ++i) { for (int i = 0; i < array.length; ++i) {
array[i] = list.get(i); array[i] = list.get(i);
@ -122,8 +129,9 @@ public abstract class TSimpleIntStreamImpl implements TIntStream {
} else { } else {
int[] array = new int[estimatedSize]; int[] array = new int[estimatedSize];
ArrayFillingConsumer consumer = new ArrayFillingConsumer(array); ArrayFillingConsumer consumer = new ArrayFillingConsumer(array);
boolean wantsMore = next(consumer); while (next(consumer)) {
assert !wantsMore : "next() should have reported done status"; // go on
}
if (consumer.index < array.length) { if (consumer.index < array.length) {
array = Arrays.copyOf(array, consumer.index); array = Arrays.copyOf(array, consumer.index);
} }
@ -134,26 +142,33 @@ public abstract class TSimpleIntStreamImpl implements TIntStream {
@Override @Override
public int reduce(int identity, IntBinaryOperator accumulator) { public int reduce(int identity, IntBinaryOperator accumulator) {
TReducingIntConsumer consumer = new TReducingIntConsumer(accumulator, identity, true); TReducingIntConsumer consumer = new TReducingIntConsumer(accumulator, identity, true);
boolean wantsMore = next(consumer); while (next(consumer)) {
assert !wantsMore : "next() should have returned true"; // go on
}
return consumer.result; return consumer.result;
} }
@Override @Override
public OptionalInt reduce(IntBinaryOperator accumulator) { public OptionalInt reduce(IntBinaryOperator accumulator) {
TReducingIntConsumer consumer = new TReducingIntConsumer(accumulator, 0, false); TReducingIntConsumer consumer = new TReducingIntConsumer(accumulator, 0, false);
boolean wantsMore = next(consumer); while (next(consumer)) {
assert !wantsMore : "next() should have returned true"; // go on
}
return consumer.initialized ? OptionalInt.of(consumer.result) : OptionalInt.empty(); return consumer.initialized ? OptionalInt.of(consumer.result) : OptionalInt.empty();
} }
@Override @Override
public <R> R collect(Supplier<R> supplier, ObjIntConsumer<R> accumulator, BiConsumer<R, R> combiner) { public <R> R collect(Supplier<R> supplier, ObjIntConsumer<R> accumulator, BiConsumer<R, R> combiner) {
R collection = supplier.get(); R collection = supplier.get();
next(e -> { while (true) {
accumulator.accept(collection, e); boolean hasMore = next(e -> {
return true; accumulator.accept(collection, e);
}); return true;
});
if (!hasMore) {
break;
}
}
return collection; return collection;
} }
@ -170,32 +185,46 @@ public abstract class TSimpleIntStreamImpl implements TIntStream {
@Override @Override
public long count() { public long count() {
TCountingIntConsumer consumer = new TCountingIntConsumer(); TCountingIntConsumer consumer = new TCountingIntConsumer();
next(consumer); while (next(consumer)) {
// go on
}
return consumer.count; return consumer.count;
} }
@Override @Override
public int sum() { public int sum() {
TSumIntConsumer consumer = new TSumIntConsumer(); TSumIntConsumer consumer = new TSumIntConsumer();
next(consumer); while (next(consumer)) {
// go on
}
return consumer.sum; return consumer.sum;
} }
@Override @Override
public OptionalDouble average() { public OptionalDouble average() {
TSumIntAsDoubleConsumer consumer = new TSumIntAsDoubleConsumer(); TSumIntAsDoubleConsumer consumer = new TSumIntAsDoubleConsumer();
next(consumer); while (next(consumer)) {
// go on
}
return consumer.count > 0 ? OptionalDouble.of(consumer.sum / consumer.count) : OptionalDouble.empty(); return consumer.count > 0 ? OptionalDouble.of(consumer.sum / consumer.count) : OptionalDouble.empty();
} }
@Override @Override
public boolean anyMatch(IntPredicate predicate) { public boolean anyMatch(IntPredicate predicate) {
return next(predicate.negate()); TAnyMatchConsumer consumer = new TAnyMatchConsumer(predicate);
while (!consumer.matched && next(consumer)) {
// go on
}
return consumer.matched;
} }
@Override @Override
public boolean allMatch(IntPredicate predicate) { public boolean allMatch(IntPredicate predicate) {
return !next(predicate); TAllMatchConsumer consumer = new TAllMatchConsumer(predicate);
while (consumer.matched && next(consumer)) {
// go on
}
return consumer.matched;
} }
@Override @Override
@ -206,7 +235,9 @@ public abstract class TSimpleIntStreamImpl implements TIntStream {
@Override @Override
public OptionalInt findFirst() { public OptionalInt findFirst() {
TFindFirstIntConsumer consumer = new TFindFirstIntConsumer(); TFindFirstIntConsumer consumer = new TFindFirstIntConsumer();
next(consumer); while (!consumer.hasAny && next(consumer)) {
// go on
}
return consumer.hasAny ? OptionalInt.of(consumer.result) : OptionalInt.empty(); return consumer.hasAny ? OptionalInt.of(consumer.result) : OptionalInt.empty();
} }
@ -275,7 +306,7 @@ public abstract class TSimpleIntStreamImpl implements TIntStream {
public abstract boolean next(IntPredicate consumer); public abstract boolean next(IntPredicate consumer);
class ArrayFillingConsumer implements IntPredicate { static class ArrayFillingConsumer implements IntPredicate {
int[] array; int[] array;
int index; int index;

View File

@ -53,13 +53,21 @@ public class TSimpleIntStreamIterator implements PrimitiveIterator.OfInt {
if (state != NEEDS_MORE) { if (state != NEEDS_MORE) {
return; return;
} }
boolean hasMore = stream.next(e -> { state = NEEDS_MORE;
lastElement = e; while (state == NEEDS_MORE) {
return false; boolean hasMore = stream.next(e -> {
}); lastElement = e;
state = hasMore ? HAS_DATA : LAST_ELEMENT; state = HAS_DATA;
if (state == LAST_ELEMENT) { return false;
stream = null; });
if (!hasMore) {
if (state == NEEDS_MORE) {
state = DONE;
} else {
state = LAST_ELEMENT;
}
stream = null;
}
} }
} }
} }

View File

@ -20,6 +20,7 @@ import java.util.function.IntConsumer;
public class TSimpleIntStreamSpliterator implements Spliterator.OfInt { public class TSimpleIntStreamSpliterator implements Spliterator.OfInt {
private TSimpleIntStreamImpl stream; private TSimpleIntStreamImpl stream;
private boolean foundItems;
private boolean done; private boolean done;
public TSimpleIntStreamSpliterator(TSimpleIntStreamImpl stream) { public TSimpleIntStreamSpliterator(TSimpleIntStreamImpl stream) {
@ -39,10 +40,14 @@ public class TSimpleIntStreamSpliterator implements Spliterator.OfInt {
if (done) { if (done) {
return false; return false;
} }
done = !stream.next(x -> { foundItems = false;
action.accept(x); while (!foundItems && !done) {
return false; done = !stream.next(x -> {
}); action.accept(x);
foundItems = true;
return false;
});
}
return true; return true;
} }

View File

@ -30,7 +30,7 @@ public class TSkippingIntStreamImpl extends TSimpleIntStreamImpl {
@Override @Override
public boolean next(IntPredicate consumer) { public boolean next(IntPredicate consumer) {
if (remaining > 0) { while (remaining > 0) {
if (!sourceStream.next(e -> --remaining > 0)) { if (!sourceStream.next(e -> --remaining > 0)) {
return false; return false;
} }

View File

@ -33,16 +33,15 @@ public class TSpecializedConcatIntStream extends TSimpleIntStreamImpl {
if (current == null) { if (current == null) {
return false; return false;
} }
while (true) { if (current.next(consumer)) {
if (current.next(consumer)) { return true;
return true; }
} if (current == first) {
if (current == first) { current = second;
current = second; return true;
} else { } else {
current = null; current = null;
return false; return false;
}
} }
} }

View File

@ -0,0 +1,35 @@
/*
* Copyright 2019 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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 TAllMatchConsumer implements LongPredicate {
public boolean matched = true;
private LongPredicate predicate;
public TAllMatchConsumer(LongPredicate predicate) {
this.predicate = predicate;
}
@Override
public boolean test(long t) {
if (!predicate.test(t)) {
matched = false;
}
return matched;
}
}

View File

@ -0,0 +1,33 @@
/*
* Copyright 2019 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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 TAnyMatchConsumer implements LongPredicate {
public boolean matched;
private LongPredicate predicate;
public TAnyMatchConsumer(LongPredicate predicate) {
this.predicate = predicate;
}
@Override
public boolean test(long t) {
matched = predicate.test(t);
return !matched;
}
}

View File

@ -30,6 +30,6 @@ public class TEmptyLongStreamImpl extends TSimpleLongStreamImpl {
@Override @Override
public long count() { public long count() {
return 1; return 0;
} }
} }

View File

@ -22,6 +22,7 @@ import org.teavm.classlib.java.util.stream.TLongStream;
public class TFlatMappingLongStreamImpl extends TSimpleLongStreamImpl { public class TFlatMappingLongStreamImpl extends TSimpleLongStreamImpl {
private TSimpleLongStreamImpl sourceStream; private TSimpleLongStreamImpl sourceStream;
private boolean currentSet;
private TLongStream current; private TLongStream current;
private PrimitiveIterator.OfLong iterator; private PrimitiveIterator.OfLong iterator;
private LongFunction<? extends TLongStream> mapper; private LongFunction<? extends TLongStream> mapper;
@ -34,42 +35,44 @@ public class TFlatMappingLongStreamImpl extends TSimpleLongStreamImpl {
@Override @Override
public boolean next(LongPredicate consumer) { public boolean next(LongPredicate consumer) {
while (true) { if (current == null) {
if (current == null) { if (done) {
if (done) { return false;
return false; }
} currentSet = false;
while (!currentSet) {
boolean hasMore = sourceStream.next(e -> { boolean hasMore = sourceStream.next(e -> {
current = mapper.apply(e); current = mapper.apply(e);
currentSet = true;
return false; return false;
}); });
if (!hasMore) { if (!hasMore) {
done = true; done = true;
} break;
if (current == null) {
done = true;
return false;
} }
} }
if (current instanceof TSimpleLongStreamImpl) { if (current == null) {
@SuppressWarnings("unchecked") return false;
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;
} }
} }
if (current instanceof TSimpleLongStreamImpl) {
TSimpleLongStreamImpl castCurrent = (TSimpleLongStreamImpl) current;
if (castCurrent.next(consumer)) {
return true;
}
current = null;
} else {
iterator = current.iterator();
while (iterator.hasNext()) {
long e = iterator.next();
if (!consumer.test(e)) {
return true;
}
}
iterator = null;
current = null;
}
return true;
} }
@Override @Override

View File

@ -102,10 +102,15 @@ public abstract class TSimpleLongStreamImpl implements TLongStream {
@Override @Override
public void forEachOrdered(LongConsumer action) { public void forEachOrdered(LongConsumer action) {
next(e -> { while (true) {
action.accept(e); boolean hasMore = next(e -> {
return true; action.accept(e);
}); return true;
});
if (!hasMore) {
return;
}
}
} }
@Override @Override
@ -113,7 +118,9 @@ public abstract class TSimpleLongStreamImpl implements TLongStream {
int estimatedSize = estimateSize(); int estimatedSize = estimateSize();
if (estimatedSize < 0) { if (estimatedSize < 0) {
List<Long> list = new ArrayList<>(); List<Long> list = new ArrayList<>();
next(list::add); while (next(list::add)) {
// go on
}
long[] array = new long[list.size()]; long[] array = new long[list.size()];
for (int i = 0; i < array.length; ++i) { for (int i = 0; i < array.length; ++i) {
array[i] = list.get(i); array[i] = list.get(i);
@ -122,8 +129,9 @@ public abstract class TSimpleLongStreamImpl implements TLongStream {
} else { } else {
long[] array = new long[estimatedSize]; long[] array = new long[estimatedSize];
ArrayFillingConsumer consumer = new ArrayFillingConsumer(array); ArrayFillingConsumer consumer = new ArrayFillingConsumer(array);
boolean wantsMore = next(consumer); while (next(consumer)) {
assert !wantsMore : "next() should have reported done status"; // go on
}
if (consumer.index < array.length) { if (consumer.index < array.length) {
array = Arrays.copyOf(array, consumer.index); array = Arrays.copyOf(array, consumer.index);
} }
@ -134,26 +142,33 @@ public abstract class TSimpleLongStreamImpl implements TLongStream {
@Override @Override
public long reduce(long identity, LongBinaryOperator accumulator) { public long reduce(long identity, LongBinaryOperator accumulator) {
TReducingLongConsumer consumer = new TReducingLongConsumer(accumulator, identity, true); TReducingLongConsumer consumer = new TReducingLongConsumer(accumulator, identity, true);
boolean wantsMore = next(consumer); while (next(consumer)) {
assert !wantsMore : "next() should have returned true"; // go on
}
return consumer.result; return consumer.result;
} }
@Override @Override
public OptionalLong reduce(LongBinaryOperator accumulator) { public OptionalLong reduce(LongBinaryOperator accumulator) {
TReducingLongConsumer consumer = new TReducingLongConsumer(accumulator, 0, false); TReducingLongConsumer consumer = new TReducingLongConsumer(accumulator, 0, false);
boolean wantsMore = next(consumer); while (next(consumer)) {
assert !wantsMore : "next() should have returned true"; // go on
}
return consumer.initialized ? OptionalLong.of(consumer.result) : OptionalLong.empty(); return consumer.initialized ? OptionalLong.of(consumer.result) : OptionalLong.empty();
} }
@Override @Override
public <R> R collect(Supplier<R> supplier, ObjLongConsumer<R> accumulator, BiConsumer<R, R> combiner) { public <R> R collect(Supplier<R> supplier, ObjLongConsumer<R> accumulator, BiConsumer<R, R> combiner) {
R collection = supplier.get(); R collection = supplier.get();
next(e -> { while (true) {
accumulator.accept(collection, e); boolean hasMore = next(e -> {
return true; accumulator.accept(collection, e);
}); return true;
});
if (!hasMore) {
break;
}
}
return collection; return collection;
} }
@ -170,32 +185,46 @@ public abstract class TSimpleLongStreamImpl implements TLongStream {
@Override @Override
public long count() { public long count() {
TCountingLongConsumer consumer = new TCountingLongConsumer(); TCountingLongConsumer consumer = new TCountingLongConsumer();
next(consumer); while (next(consumer)) {
// go on
}
return consumer.count; return consumer.count;
} }
@Override @Override
public long sum() { public long sum() {
TSumLongConsumer consumer = new TSumLongConsumer(); TSumLongConsumer consumer = new TSumLongConsumer();
next(consumer); while (next(consumer)) {
// go on
}
return consumer.sum; return consumer.sum;
} }
@Override @Override
public OptionalDouble average() { public OptionalDouble average() {
TSumLongAsDoubleConsumer consumer = new TSumLongAsDoubleConsumer(); TSumLongAsDoubleConsumer consumer = new TSumLongAsDoubleConsumer();
next(consumer); while (next(consumer)) {
// go on
}
return consumer.count > 0 ? OptionalDouble.of(consumer.sum / consumer.count) : OptionalDouble.empty(); return consumer.count > 0 ? OptionalDouble.of(consumer.sum / consumer.count) : OptionalDouble.empty();
} }
@Override @Override
public boolean anyMatch(LongPredicate predicate) { public boolean anyMatch(LongPredicate predicate) {
return next(predicate.negate()); TAnyMatchConsumer consumer = new TAnyMatchConsumer(predicate);
while (!consumer.matched && next(consumer)) {
// go on
}
return consumer.matched;
} }
@Override @Override
public boolean allMatch(LongPredicate predicate) { public boolean allMatch(LongPredicate predicate) {
return !next(predicate); TAllMatchConsumer consumer = new TAllMatchConsumer(predicate);
while (consumer.matched && next(consumer)) {
// go on
}
return consumer.matched;
} }
@Override @Override
@ -206,7 +235,9 @@ public abstract class TSimpleLongStreamImpl implements TLongStream {
@Override @Override
public OptionalLong findFirst() { public OptionalLong findFirst() {
TFindFirstLongConsumer consumer = new TFindFirstLongConsumer(); TFindFirstLongConsumer consumer = new TFindFirstLongConsumer();
next(consumer); while (!consumer.hasAny && next(consumer)) {
// go on
}
return consumer.hasAny ? OptionalLong.of(consumer.result) : OptionalLong.empty(); return consumer.hasAny ? OptionalLong.of(consumer.result) : OptionalLong.empty();
} }
@ -270,7 +301,7 @@ public abstract class TSimpleLongStreamImpl implements TLongStream {
public abstract boolean next(LongPredicate consumer); public abstract boolean next(LongPredicate consumer);
class ArrayFillingConsumer implements LongPredicate { static class ArrayFillingConsumer implements LongPredicate {
long[] array; long[] array;
int index; int index;

View File

@ -53,13 +53,21 @@ public class TSimpleLongStreamIterator implements PrimitiveIterator.OfLong {
if (state != NEEDS_MORE) { if (state != NEEDS_MORE) {
return; return;
} }
boolean hasMore = stream.next(e -> { state = NEEDS_MORE;
lastElement = e; while (state == NEEDS_MORE) {
return false; boolean hasMore = stream.next(e -> {
}); lastElement = e;
state = hasMore ? HAS_DATA : LAST_ELEMENT; state = HAS_DATA;
if (state == LAST_ELEMENT) { return false;
stream = null; });
if (!hasMore) {
if (state == NEEDS_MORE) {
state = DONE;
} else {
state = LAST_ELEMENT;
}
stream = null;
}
} }
} }
} }

View File

@ -20,6 +20,7 @@ import java.util.function.LongConsumer;
public class TSimpleLongStreamSpliterator implements Spliterator.OfLong { public class TSimpleLongStreamSpliterator implements Spliterator.OfLong {
private TSimpleLongStreamImpl stream; private TSimpleLongStreamImpl stream;
private boolean foundItems;
private boolean done; private boolean done;
public TSimpleLongStreamSpliterator(TSimpleLongStreamImpl stream) { public TSimpleLongStreamSpliterator(TSimpleLongStreamImpl stream) {
@ -39,10 +40,14 @@ public class TSimpleLongStreamSpliterator implements Spliterator.OfLong {
if (done) { if (done) {
return false; return false;
} }
done = !stream.next(x -> { foundItems = false;
action.accept(x); while (!foundItems && !done) {
return false; done = !stream.next(x -> {
}); action.accept(x);
foundItems = true;
return false;
});
}
return true; return true;
} }

View File

@ -30,7 +30,7 @@ public class TSkippingLongStreamImpl extends TSimpleLongStreamImpl {
@Override @Override
public boolean next(LongPredicate consumer) { public boolean next(LongPredicate consumer) {
if (remaining > 0) { while (remaining > 0) {
if (!sourceStream.next(e -> --remaining > 0)) { if (!sourceStream.next(e -> --remaining > 0)) {
return false; return false;
} }

View File

@ -33,16 +33,15 @@ public class TSpecializedConcatLongStream extends TSimpleLongStreamImpl {
if (current == null) { if (current == null) {
return false; return false;
} }
while (true) { if (current.next(consumer)) {
if (current.next(consumer)) { return true;
return true; }
} if (current == first) {
if (current == first) { current = second;
current = second; return true;
} else { } else {
current = null; current = null;
return false; return false;
}
} }
} }

View File

@ -19,13 +19,15 @@ import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.teavm.classlib.java.util.stream.Helper.appendDoubleNumbersTo;
import static org.teavm.classlib.java.util.stream.Helper.testDoubleStream;
import static org.teavm.classlib.java.util.stream.Helper.testIntStream;
import static org.teavm.classlib.java.util.stream.Helper.testIntegerStream;
import static org.teavm.classlib.java.util.stream.Helper.testLongStream;
import java.util.PrimitiveIterator; import java.util.PrimitiveIterator;
import java.util.Spliterator; 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 java.util.stream.DoubleStream;
import java.util.stream.LongStream;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.teavm.junit.TeaVMTestRunner; import org.teavm.junit.TeaVMTestRunner;
@ -34,85 +36,94 @@ import org.teavm.junit.TeaVMTestRunner;
public class DoubleStreamTest { public class DoubleStreamTest {
@Test @Test
public void forEachWorks() { public void forEachWorks() {
StringBuilder sb = new StringBuilder(); testDoubleStream(() -> DoubleStream.of(1, 2, 3), 1, 2, 3);
DoubleStream.of(1, 2, 3).forEach(appendNumbersTo(sb)); testDoubleStream(() -> DoubleStream.concat(DoubleStream.of(1), DoubleStream.of(2, 3)), 1, 2, 3);
assertEquals("1.0;2.0;3.0;", sb.toString()); testDoubleStream(() -> DoubleStream.concat(DoubleStream.empty(), DoubleStream.of(1, 2, 3)), 1, 2, 3);
} }
@Test @Test
public void mapWorks() { public void mapWorks() {
StringBuilder sb = new StringBuilder(); testDoubleStream(() -> DoubleStream.of(1, 2, 3).map(n -> n * n), 1, 4, 9);
DoubleStream.of(1, 2, 3).map(n -> n * n).forEach(appendNumbersTo(sb)); testDoubleStream(() -> DoubleStream.concat(DoubleStream.of(1), DoubleStream.of(2, 3))
assertEquals("1.0;4.0;9.0;", sb.toString()); .map(n -> n * n), 1, 4, 9);
testDoubleStream(() -> DoubleStream.concat(DoubleStream.empty(), DoubleStream.of(1, 2, 3))
.map(n -> n * n), 1, 4, 9);
} }
@Test @Test
public void mapToObjWorks() { public void mapToObjWorks() {
String result = DoubleStream.of(1, 2, 3).mapToObj(n -> String.valueOf(n * n)).collect(Collectors.joining(";")); testIntegerStream(() -> DoubleStream.of(1, 2, 3).mapToObj(n -> (int) (n * n)), 1, 4, 9);
assertEquals("1.0;4.0;9.0", result); testIntegerStream(() -> DoubleStream.concat(DoubleStream.of(1), DoubleStream.of(2, 3))
.mapToObj(n -> (int) (n * n)), 1, 4, 9);
testIntegerStream(() -> DoubleStream.concat(DoubleStream.empty(), DoubleStream.of(1, 2, 3))
.mapToObj(n -> (int) (n * n)), 1, 4, 9);
} }
@Test @Test
public void mapToIntWorks() { public void mapToIntWorks() {
StringBuilder sb = new StringBuilder(); testIntStream(() -> DoubleStream.of(1, 2, 3).mapToInt(n -> (int) (n * n)), 1, 4, 9);
DoubleStream.of(1, 2, 3).mapToInt(n -> (int) (n * n)).forEach(appendIntNumbersTo(sb)); testIntStream(() -> DoubleStream.concat(DoubleStream.of(1), DoubleStream.of(2, 3))
assertEquals("1;4;9;", sb.toString()); .mapToInt(n -> (int) (n * n)), 1, 4, 9);
testIntStream(() -> DoubleStream.concat(DoubleStream.empty(), DoubleStream.of(1, 2, 3))
.mapToInt(n -> (int) (n * n)), 1, 4, 9);
} }
@Test @Test
public void mapToLongWorks() { public void mapToLongWorks() {
StringBuilder sb = new StringBuilder(); testLongStream(() -> DoubleStream.of(1, 2, 3).mapToLong(n -> (long) (n * n)), 1, 4, 9);
DoubleStream.of(1, 2, 3).mapToLong(n -> (long) (n * n)).forEach(appendLongNumbersTo(sb)); testLongStream(() -> DoubleStream.concat(DoubleStream.of(1), DoubleStream.of(2, 3))
assertEquals("1;4;9;", sb.toString()); .mapToLong(n -> (long) (n * n)), 1, 4, 9);
testLongStream(() -> DoubleStream.concat(DoubleStream.empty(), DoubleStream.of(1, 2, 3))
.mapToLong(n -> (long) (n * n)), 1, 4, 9);
} }
@Test @Test
public void filterWorks() { public void filterWorks() {
StringBuilder sb = new StringBuilder(); testDoubleStream(() -> DoubleStream.of(1, 2, 3, 4, 5, 6).filter(n -> (n % 2) == 0), 2, 4, 6);
DoubleStream.of(1, 2, 3, 4, 5, 6).filter(n -> (n % 2) == 0).forEach(appendNumbersTo(sb)); testDoubleStream(() -> DoubleStream.concat(DoubleStream.of(1), DoubleStream.of(2, 3, 4, 5, 6))
assertEquals("2.0;4.0;6.0;", sb.toString()); .filter(n -> ((int) n & 1) == 0), 2, 4, 6);
testDoubleStream(() -> DoubleStream.concat(DoubleStream.empty(), DoubleStream.of(1, 2, 3, 4, 5, 6))
.filter(n -> ((int) n & 1) == 0), 2, 4, 6);
} }
@Test @Test
public void flatMapWorks() { public void flatMapWorks() {
StringBuilder sb = new StringBuilder(); testDoubleStream(() -> DoubleStream.of(1, 3).flatMap(n -> DoubleStream.of(n, n + 1)), 1, 2, 3, 4);
DoubleStream.of(1, 3).flatMap(n -> DoubleStream.of(n, n + 1)).forEach(appendNumbersTo(sb)); testDoubleStream(() -> DoubleStream.of(1, 3).flatMap(n -> DoubleStream.of(n, n + 1)).skip(1), 2, 3, 4);
assertEquals("1.0;2.0;3.0;4.0;", sb.toString()); testDoubleStream(() -> DoubleStream.of(1, 4).flatMap(n -> DoubleStream.of(n, n + 1, n + 2)).skip(3), 4, 5, 6);
sb.setLength(0); testDoubleStream(() -> DoubleStream.of(1, 3, 100)
DoubleStream.of(1, 3).flatMap(n -> DoubleStream.of(n, n + 1)).skip(1).forEach(appendNumbersTo(sb)); .flatMap(n -> n < 100 ? DoubleStream.of(n, n + 1) : DoubleStream.empty()), 1, 2, 3, 4);
assertEquals("2.0;3.0;4.0;", sb.toString()); testDoubleStream(() -> DoubleStream.of(100, 1, 3)
.flatMap(n -> n < 100 ? DoubleStream.of(n, n + 1) : DoubleStream.empty()), 1, 2, 3, 4);
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 @Test
public void skipWorks() { public void skipWorks() {
for (int i = 0; i <= 6; ++i) { for (int i = 0; i <= 5; ++i) {
StringBuilder sb = new StringBuilder(); int index = i;
DoubleStream.iterate(1, n -> n + 1).limit(5).skip(i).forEach(appendNumbersTo(sb)); double[] expected = new double[5 - i];
StringBuilder expected = new StringBuilder();
for (int j = i; j < 5; ++j) { for (int j = i; j < 5; ++j) {
expected.append((double) j + 1).append(';'); expected[j - i] = j + 1;
} }
assertEquals("Error skipping " + i + " elements", expected.toString(), sb.toString()); testDoubleStream(() -> DoubleStream.iterate(1, n -> n + 1).limit(5).skip(index), expected);
testDoubleStream(() -> DoubleStream.concat(DoubleStream.of(1), DoubleStream.iterate(2, n -> n + 1)
.limit(4)).skip(index), expected);
testDoubleStream(() -> DoubleStream.concat(DoubleStream.empty(), DoubleStream.iterate(1, n -> n + 1)
.limit(5)).skip(index), expected);
} }
} }
@Test @Test
public void limitWorks() { public void limitWorks() {
for (int i = 0; i <= 3; ++i) { for (int i = 0; i <= 3; ++i) {
StringBuilder sb = new StringBuilder(); int index = i;
DoubleStream.iterate(1, n -> n + 1).limit(i).forEach(appendNumbersTo(sb)); long[] expected = new long[i];
for (int j = 0; j < expected.length; ++j) {
StringBuilder expected = new StringBuilder(); expected[j] = j + 1;
for (int j = 0; j < i; ++j) {
expected.append((double) j + 1).append(';');
} }
assertEquals("Error limiting to " + i + " elements", expected.toString(), sb.toString());
testLongStream(() -> LongStream.iterate(1, n -> n + 1).limit(index), expected);
} }
} }
@ -135,19 +146,19 @@ public class DoubleStreamTest {
@Test @Test
public void distinctWorks() { public void distinctWorks() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
DoubleStream.of(2, 3, 2, 3).distinct().forEach(appendNumbersTo(sb)); DoubleStream.of(2, 3, 2, 3).distinct().forEach(appendDoubleNumbersTo(sb));
assertEquals("2.0;3.0;", sb.toString()); assertEquals("2.0;3.0;", sb.toString());
sb.setLength(0); sb.setLength(0);
DoubleStream.of(2, 3, 2, 3).skip(1).distinct().forEach(appendNumbersTo(sb)); DoubleStream.of(2, 3, 2, 3).skip(1).distinct().forEach(appendDoubleNumbersTo(sb));
assertEquals("3.0;2.0;", sb.toString()); assertEquals("3.0;2.0;", sb.toString());
sb.setLength(0); sb.setLength(0);
DoubleStream.of(2, 3, 2, 3).limit(2).distinct().forEach(appendNumbersTo(sb)); DoubleStream.of(2, 3, 2, 3).limit(2).distinct().forEach(appendDoubleNumbersTo(sb));
assertEquals("2.0;3.0;", sb.toString()); assertEquals("2.0;3.0;", sb.toString());
sb.setLength(0); sb.setLength(0);
DoubleStream.of(2, 2, 3, 2, 4, 3, 1).distinct().forEach(appendNumbersTo(sb)); DoubleStream.of(2, 2, 3, 2, 4, 3, 1).distinct().forEach(appendDoubleNumbersTo(sb));
assertEquals("2.0;3.0;4.0;1.0;", sb.toString()); assertEquals("2.0;3.0;4.0;1.0;", sb.toString());
} }
@ -164,22 +175,22 @@ public class DoubleStreamTest {
@Test @Test
public void concatWorks() { public void concatWorks() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
DoubleStream.concat(DoubleStream.of(1, 2), DoubleStream.of(3, 4)).forEach(appendNumbersTo(sb)); DoubleStream.concat(DoubleStream.of(1, 2), DoubleStream.of(3, 4)).forEach(appendDoubleNumbersTo(sb));
assertEquals("1.0;2.0;3.0;4.0;", sb.toString()); assertEquals("1.0;2.0;3.0;4.0;", sb.toString());
sb.setLength(0); sb.setLength(0);
DoubleStream.concat(DoubleStream.of(1, 2), DoubleStream.of(3, 4)).skip(1).forEach(appendNumbersTo(sb)); DoubleStream.concat(DoubleStream.of(1, 2), DoubleStream.of(3, 4)).skip(1).forEach(appendDoubleNumbersTo(sb));
assertEquals("2.0;3.0;4.0;", sb.toString()); assertEquals("2.0;3.0;4.0;", sb.toString());
sb.setLength(0); sb.setLength(0);
DoubleStream.concat(DoubleStream.of(1, 2), DoubleStream.of(3, 4, 5)).skip(3).forEach(appendNumbersTo(sb)); DoubleStream.concat(DoubleStream.of(1, 2), DoubleStream.of(3, 4, 5)).skip(3).forEach(appendDoubleNumbersTo(sb));
assertEquals("4.0;5.0;", sb.toString()); assertEquals("4.0;5.0;", sb.toString());
} }
@Test @Test
public void peekWorks() { public void peekWorks() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
DoubleStream.of(1, 2, 3).peek(appendNumbersTo(sb)).map(n -> n + 10).forEach(appendNumbersTo(sb)); DoubleStream.of(1, 2, 3).peek(appendDoubleNumbersTo(sb)).map(n -> n + 10).forEach(appendDoubleNumbersTo(sb));
assertEquals("1.0;11.0;2.0;12.0;3.0;13.0;", sb.toString()); assertEquals("1.0;11.0;2.0;12.0;3.0;13.0;", sb.toString());
} }
@ -196,31 +207,31 @@ public class DoubleStreamTest {
@Test @Test
public void streamOfOneElement() { public void streamOfOneElement() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
DoubleStream.of(5).forEach(appendNumbersTo(sb)); DoubleStream.of(5).forEach(appendDoubleNumbersTo(sb));
assertEquals("5.0;", sb.toString()); assertEquals("5.0;", sb.toString());
sb.setLength(0); sb.setLength(0);
DoubleStream.of(5).skip(1).forEach(appendNumbersTo(sb)); DoubleStream.of(5).skip(1).forEach(appendDoubleNumbersTo(sb));
assertEquals("", sb.toString()); assertEquals("", sb.toString());
sb.setLength(0); sb.setLength(0);
DoubleStream.concat(DoubleStream.of(5), DoubleStream.of(6)).forEach(appendNumbersTo(sb)); DoubleStream.concat(DoubleStream.of(5), DoubleStream.of(6)).forEach(appendDoubleNumbersTo(sb));
assertEquals("5.0;6.0;", sb.toString()); assertEquals("5.0;6.0;", sb.toString());
} }
@Test @Test
public void sortedStream() { public void sortedStream() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
DoubleStream.of(5, 7, 1, 2, 4, 3).sorted().forEach(appendNumbersTo(sb)); DoubleStream.of(5, 7, 1, 2, 4, 3).sorted().forEach(appendDoubleNumbersTo(sb));
assertEquals("1.0;2.0;3.0;4.0;5.0;7.0;", sb.toString()); assertEquals("1.0;2.0;3.0;4.0;5.0;7.0;", sb.toString());
sb.setLength(0); sb.setLength(0);
DoubleStream.of(2, 3, 1).peek(appendNumbersTo(sb)).sorted().limit(2).map(n -> n + 10) DoubleStream.of(2, 3, 1).peek(appendDoubleNumbersTo(sb)).sorted().limit(2).map(n -> n + 10)
.forEach(appendNumbersTo(sb)); .forEach(appendDoubleNumbersTo(sb));
assertEquals("2.0;3.0;1.0;11.0;12.0;", sb.toString()); assertEquals("2.0;3.0;1.0;11.0;12.0;", sb.toString());
sb.setLength(0); sb.setLength(0);
DoubleStream.of(2, 3, 1).peek(appendNumbersTo(sb)).sorted().limit(0).forEach(appendNumbersTo(sb)); DoubleStream.of(2, 3, 1).peek(appendDoubleNumbersTo(sb)).sorted().limit(0).forEach(appendDoubleNumbersTo(sb));
assertEquals("2.0;3.0;1.0;", sb.toString()); assertEquals("2.0;3.0;1.0;", sb.toString());
} }
@ -299,7 +310,7 @@ public class DoubleStreamTest {
sb.setLength(0); sb.setLength(0);
iterator = DoubleStream.of(1, 2, 3).iterator(); iterator = DoubleStream.of(1, 2, 3).iterator();
iterator.forEachRemaining(appendNumbersTo(sb)); iterator.forEachRemaining(appendDoubleNumbersTo(sb));
assertEquals("1.0;2.0;3.0;", sb.toString()); assertEquals("1.0;2.0;3.0;", sb.toString());
} }
@ -307,14 +318,14 @@ public class DoubleStreamTest {
public void spliterator() { public void spliterator() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
Spliterator.OfDouble spliterator = DoubleStream.of(1, 2, 3).spliterator(); Spliterator.OfDouble spliterator = DoubleStream.of(1, 2, 3).spliterator();
while (spliterator.tryAdvance(appendNumbersTo(sb))) { while (spliterator.tryAdvance(appendDoubleNumbersTo(sb))) {
// continue // continue
} }
assertEquals("1.0;2.0;3.0;", sb.toString()); assertEquals("1.0;2.0;3.0;", sb.toString());
sb.setLength(0); sb.setLength(0);
spliterator = DoubleStream.of(1, 2, 3).spliterator(); spliterator = DoubleStream.of(1, 2, 3).spliterator();
spliterator.forEachRemaining(appendNumbersTo(sb)); spliterator.forEachRemaining(appendDoubleNumbersTo(sb));
assertEquals("1.0;2.0;3.0;", sb.toString()); assertEquals("1.0;2.0;3.0;", sb.toString());
} }
@ -323,16 +334,4 @@ public class DoubleStreamTest {
assertEquals(2.5, DoubleStream.of(1, 2, 3, 4).average().getAsDouble(), 0.001); assertEquals(2.5, DoubleStream.of(1, 2, 3, 4).average().getAsDouble(), 0.001);
assertFalse(DoubleStream.empty().average().isPresent()); 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(';');
}
} }

View File

@ -0,0 +1,208 @@
/*
* Copyright 2019 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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 static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.Iterator;
import java.util.PrimitiveIterator;
import java.util.function.Consumer;
import java.util.function.DoubleConsumer;
import java.util.function.IntConsumer;
import java.util.function.LongConsumer;
import java.util.function.Supplier;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
final class Helper {
private Helper() {
}
static void testIntegerStream(Supplier<Stream<Integer>> streamSupplier, Integer... expected) {
StringBuilder sb = new StringBuilder();
for (Integer e : expected) {
sb.append(e).append(';');
}
String expectedText = sb.toString();
sb.setLength(0);
streamSupplier.get().forEach(appendNumbersTo(sb));
assertEquals(expectedText, sb.toString());
sb.setLength(0);
Iterator<Integer> iter = streamSupplier.get().iterator();
while (iter.hasNext()) {
sb.append(iter.next()).append(';');
}
assertEquals(expectedText, sb.toString());
assertEquals(expected.length, streamSupplier.get().count());
if (expected.length > 0) {
int max = expected[0];
for (Integer e : expected) {
max = Math.max(max, e);
}
int notInCollection = max + 1;
int inCollection = expected[0];
assertTrue(streamSupplier.get().allMatch(e -> e < notInCollection));
assertFalse(streamSupplier.get().allMatch(e -> e < inCollection));
assertTrue(streamSupplier.get().anyMatch(e -> e == inCollection));
assertFalse(streamSupplier.get().anyMatch(e -> e == notInCollection));
} else {
assertTrue(streamSupplier.get().allMatch(e -> false));
assertTrue(streamSupplier.get().allMatch(e -> true));
assertFalse(streamSupplier.get().anyMatch(e -> true));
assertFalse(streamSupplier.get().anyMatch(e -> false));
}
}
static void testIntStream(Supplier<IntStream> streamSupplier, int... expected) {
StringBuilder sb = new StringBuilder();
for (int e : expected) {
sb.append(e).append(';');
}
String expectedText = sb.toString();
sb.setLength(0);
streamSupplier.get().forEach(appendIntNumbersTo(sb));
assertEquals(expectedText, sb.toString());
sb.setLength(0);
PrimitiveIterator.OfInt iter = streamSupplier.get().iterator();
while (iter.hasNext()) {
sb.append(iter.next()).append(';');
}
assertEquals(expectedText, sb.toString());
assertEquals(expected.length, streamSupplier.get().count());
if (expected.length > 0) {
int max = expected[0];
for (int e : expected) {
max = Math.max(max, e);
}
int notInCollection = max + 1;
int inCollection = expected[0];
assertTrue(streamSupplier.get().allMatch(e -> e < notInCollection));
assertFalse(streamSupplier.get().allMatch(e -> e < inCollection));
assertTrue(streamSupplier.get().anyMatch(e -> e == inCollection));
assertFalse(streamSupplier.get().anyMatch(e -> e == notInCollection));
} else {
assertTrue(streamSupplier.get().allMatch(e -> false));
assertTrue(streamSupplier.get().allMatch(e -> true));
assertFalse(streamSupplier.get().anyMatch(e -> true));
assertFalse(streamSupplier.get().anyMatch(e -> false));
}
}
static void testLongStream(Supplier<LongStream> streamSupplier, long... expected) {
StringBuilder sb = new StringBuilder();
for (long e : expected) {
sb.append(e).append(';');
}
String expectedText = sb.toString();
sb.setLength(0);
streamSupplier.get().forEach(appendLongNumbersTo(sb));
assertEquals(expectedText, sb.toString());
sb.setLength(0);
PrimitiveIterator.OfLong iter = streamSupplier.get().iterator();
while (iter.hasNext()) {
sb.append(iter.next()).append(';');
}
assertEquals(expectedText, sb.toString());
assertEquals(expected.length, streamSupplier.get().count());
if (expected.length > 0) {
long max = expected[0];
for (long e : expected) {
max = Math.max(max, e);
}
long notInCollection = max + 1;
long inCollection = expected[0];
assertTrue(streamSupplier.get().allMatch(e -> e < notInCollection));
assertFalse(streamSupplier.get().allMatch(e -> e < inCollection));
assertTrue(streamSupplier.get().anyMatch(e -> e == inCollection));
assertFalse(streamSupplier.get().anyMatch(e -> e == notInCollection));
} else {
assertTrue(streamSupplier.get().allMatch(e -> false));
assertTrue(streamSupplier.get().allMatch(e -> true));
assertFalse(streamSupplier.get().anyMatch(e -> true));
assertFalse(streamSupplier.get().anyMatch(e -> false));
}
}
static void testDoubleStream(Supplier<DoubleStream> streamSupplier, double... expected) {
StringBuilder sb = new StringBuilder();
for (double e : expected) {
sb.append(e).append(';');
}
String expectedText = sb.toString();
sb.setLength(0);
streamSupplier.get().forEach(appendDoubleNumbersTo(sb));
assertEquals(expectedText, sb.toString());
sb.setLength(0);
PrimitiveIterator.OfDouble iter = streamSupplier.get().iterator();
while (iter.hasNext()) {
sb.append(iter.next()).append(';');
}
assertEquals(expectedText, sb.toString());
assertEquals(expected.length, streamSupplier.get().count());
if (expected.length > 0) {
double max = expected[0];
for (double e : expected) {
max = Math.max(max, e);
}
double notInCollection = max + 1;
double inCollection = expected[0];
assertTrue(streamSupplier.get().allMatch(e -> e < notInCollection));
assertFalse(streamSupplier.get().allMatch(e -> e < inCollection));
assertTrue(streamSupplier.get().anyMatch(e -> e == inCollection));
assertFalse(streamSupplier.get().anyMatch(e -> e == notInCollection));
} else {
assertTrue(streamSupplier.get().allMatch(e -> false));
assertTrue(streamSupplier.get().allMatch(e -> true));
assertFalse(streamSupplier.get().anyMatch(e -> true));
assertFalse(streamSupplier.get().anyMatch(e -> false));
}
}
static Consumer<Integer> appendNumbersTo(StringBuilder sb) {
return n -> sb.append(n).append(';');
}
static IntConsumer appendIntNumbersTo(StringBuilder sb) {
return n -> sb.append(n).append(';');
}
static LongConsumer appendLongNumbersTo(StringBuilder sb) {
return n -> sb.append(n).append(';');
}
static DoubleConsumer appendDoubleNumbersTo(StringBuilder sb) {
return n -> sb.append(n).append(';');
}
}

View File

@ -19,12 +19,13 @@ import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.teavm.classlib.java.util.stream.Helper.appendIntNumbersTo;
import static org.teavm.classlib.java.util.stream.Helper.testDoubleStream;
import static org.teavm.classlib.java.util.stream.Helper.testIntStream;
import static org.teavm.classlib.java.util.stream.Helper.testIntegerStream;
import static org.teavm.classlib.java.util.stream.Helper.testLongStream;
import java.util.PrimitiveIterator; import java.util.PrimitiveIterator;
import java.util.Spliterator; 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 java.util.stream.IntStream;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -34,85 +35,88 @@ import org.teavm.junit.TeaVMTestRunner;
public class IntStreamTest { public class IntStreamTest {
@Test @Test
public void forEachWorks() { public void forEachWorks() {
StringBuilder sb = new StringBuilder(); testIntStream(() -> IntStream.of(1, 2, 3), 1, 2, 3);
IntStream.of(1, 2, 3).forEach(appendNumbersTo(sb)); testIntStream(() -> IntStream.concat(IntStream.of(1), IntStream.of(2, 3)), 1, 2, 3);
assertEquals("1;2;3;", sb.toString()); testIntStream(() -> IntStream.concat(IntStream.empty(), IntStream.of(1, 2, 3)), 1, 2, 3);
} }
@Test @Test
public void mapWorks() { public void mapWorks() {
StringBuilder sb = new StringBuilder(); testIntStream(() -> IntStream.of(1, 2, 3).map(n -> n * n), 1, 4, 9);
IntStream.of(1, 2, 3).map(n -> n * n).forEach(appendNumbersTo(sb)); testIntStream(() -> IntStream.concat(IntStream.of(1), IntStream.of(2, 3)).map(n -> n * n), 1, 4, 9);
assertEquals("1;4;9;", sb.toString()); testIntStream(() -> IntStream.concat(IntStream.empty(), IntStream.of(1, 2, 3)).map(n -> n * n), 1, 4, 9);
} }
@Test @Test
public void mapToObjWorks() { public void mapToObjWorks() {
String result = IntStream.of(1, 2, 3).mapToObj(n -> String.valueOf(n * n)).collect(Collectors.joining(";")); testIntegerStream(() -> IntStream.of(1, 2, 3).mapToObj(n -> n * n), 1, 4, 9);
assertEquals("1;4;9", result); testIntegerStream(() -> IntStream.concat(IntStream.of(1), IntStream.of(2, 3)).mapToObj(n -> n * n), 1, 4, 9);
testIntegerStream(() -> IntStream.concat(IntStream.empty(), IntStream.of(1, 2, 3))
.mapToObj(n -> n * n), 1, 4, 9);
} }
@Test @Test
public void mapToLongWorks() { public void mapToLongWorks() {
StringBuilder sb = new StringBuilder(); testLongStream(() -> IntStream.of(1, 2, 3).mapToLong(n -> n * n), 1, 4, 9);
IntStream.of(1, 2, 3).mapToLong(n -> n * n).forEach(appendLongNumbersTo(sb)); testLongStream(() -> IntStream.concat(IntStream.of(1), IntStream.of(2, 3)).mapToLong(n -> n * n), 1, 4, 9);
assertEquals("1;4;9;", sb.toString()); testLongStream(() -> IntStream.concat(IntStream.empty(), IntStream.of(1, 2, 3)).mapToLong(n -> n * n), 1, 4, 9);
} }
@Test @Test
public void mapToDoubleWorks() { public void mapToDoubleWorks() {
StringBuilder sb = new StringBuilder(); testDoubleStream(() -> IntStream.of(1, 2, 3).mapToDouble(n -> n * n), 1, 4, 9);
IntStream.of(1, 2, 3).mapToDouble(n -> n * n).forEach(appendDoubleNumbersTo(sb)); testDoubleStream(() -> IntStream.concat(IntStream.of(1), IntStream.of(2, 3)).mapToDouble(n -> n * n), 1, 4, 9);
assertEquals("1.0;4.0;9.0;", sb.toString()); testDoubleStream(() -> IntStream.concat(IntStream.empty(), IntStream.of(1, 2, 3)).mapToDouble(n -> n * n),
1, 4, 9);
} }
@Test @Test
public void filterWorks() { public void filterWorks() {
StringBuilder sb = new StringBuilder(); testIntStream(() -> IntStream.of(1, 2, 3, 4, 5, 6).filter(n -> (n & 1) == 0), 2, 4, 6);
IntStream.of(1, 2, 3, 4, 5, 6).filter(n -> (n & 1) == 0).forEach(appendNumbersTo(sb)); testIntStream(() -> IntStream.concat(IntStream.of(1), IntStream.of(2, 3, 4, 5, 6))
assertEquals("2;4;6;", sb.toString()); .filter(n -> (n & 1) == 0), 2, 4, 6);
testIntStream(() -> IntStream.concat(IntStream.empty(), IntStream.of(1, 2, 3, 4, 5, 6))
.filter(n -> (n & 1) == 0), 2, 4, 6);
} }
@Test @Test
public void flatMapWorks() { public void flatMapWorks() {
StringBuilder sb = new StringBuilder(); testIntStream(() -> IntStream.of(1, 3).flatMap(n -> IntStream.of(n, n + 1)), 1, 2, 3, 4);
IntStream.of(1, 3).flatMap(n -> IntStream.of(n, n + 1)).forEach(appendNumbersTo(sb)); testIntStream(() -> IntStream.of(1, 3).flatMap(n -> IntStream.of(n, n + 1)).skip(1), 2, 3, 4);
assertEquals("1;2;3;4;", sb.toString()); testIntStream(() -> IntStream.of(1, 4).flatMap(n -> IntStream.of(n, n + 1, n + 2)).skip(3), 4, 5, 6);
sb.setLength(0); testIntStream(() -> IntStream.of(1, 3, 100)
IntStream.of(1, 3).flatMap(n -> IntStream.of(n, n + 1)).skip(1).forEach(appendNumbersTo(sb)); .flatMap(n -> n < 100 ? IntStream.of(n, n + 1) : IntStream.empty()), 1, 2, 3, 4);
assertEquals("2;3;4;", sb.toString()); testIntStream(() -> IntStream.of(100, 1, 3)
.flatMap(n -> n < 100 ? IntStream.of(n, n + 1) : IntStream.empty()), 1, 2, 3, 4);
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 @Test
public void skipWorks() { public void skipWorks() {
for (int i = 0; i <= 6; ++i) { for (int i = 0; i <= 5; ++i) {
StringBuilder sb = new StringBuilder(); int index = i;
IntStream.iterate(1, n -> n + 1).limit(5).skip(i).forEach(appendNumbersTo(sb)); int[] expected = new int[5 - i];
StringBuilder expected = new StringBuilder();
for (int j = i; j < 5; ++j) { for (int j = i; j < 5; ++j) {
expected.append(j + 1).append(';'); expected[j - i] = j + 1;
} }
assertEquals("Error skipping " + i + " elements", expected.toString(), sb.toString()); testIntStream(() -> IntStream.iterate(1, n -> n + 1).limit(5).skip(index), expected);
testIntStream(() -> IntStream.concat(IntStream.of(1), IntStream.iterate(2, n -> n + 1).limit(4))
.skip(index), expected);
testIntStream(() -> IntStream.concat(IntStream.empty(), IntStream.iterate(1, n -> n + 1).limit(5))
.skip(index), expected);
} }
} }
@Test @Test
public void limitWorks() { public void limitWorks() {
for (int i = 0; i <= 3; ++i) { for (int i = 0; i <= 3; ++i) {
StringBuilder sb = new StringBuilder(); int index = i;
IntStream.iterate(1, n -> n + 1).limit(i).forEach(appendNumbersTo(sb)); int[] expected = new int[i];
for (int j = 0; j < expected.length; ++j) {
StringBuilder expected = new StringBuilder(); expected[j] = j + 1;
for (int j = 0; j < i; ++j) {
expected.append(j + 1).append(';');
} }
assertEquals("Error limiting to " + i + " elements", expected.toString(), sb.toString());
testIntStream(() -> IntStream.iterate(1, n -> n + 1).limit(index), expected);
} }
} }
@ -153,22 +157,22 @@ public class IntStreamTest {
@Test @Test
public void concatWorks() { public void concatWorks() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
IntStream.concat(IntStream.of(1, 2), IntStream.of(3, 4)).forEach(appendNumbersTo(sb)); IntStream.concat(IntStream.of(1, 2), IntStream.of(3, 4)).forEach(appendIntNumbersTo(sb));
assertEquals("1;2;3;4;", sb.toString()); assertEquals("1;2;3;4;", sb.toString());
sb.setLength(0); sb.setLength(0);
IntStream.concat(IntStream.of(1, 2), IntStream.of(3, 4)).skip(1).forEach(appendNumbersTo(sb)); IntStream.concat(IntStream.of(1, 2), IntStream.of(3, 4)).skip(1).forEach(appendIntNumbersTo(sb));
assertEquals("2;3;4;", sb.toString()); assertEquals("2;3;4;", sb.toString());
sb.setLength(0); sb.setLength(0);
IntStream.concat(IntStream.of(1, 2), IntStream.of(3, 4, 5)).skip(3).forEach(appendNumbersTo(sb)); IntStream.concat(IntStream.of(1, 2), IntStream.of(3, 4, 5)).skip(3).forEach(appendIntNumbersTo(sb));
assertEquals("4;5;", sb.toString()); assertEquals("4;5;", sb.toString());
} }
@Test @Test
public void peekWorks() { public void peekWorks() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
IntStream.of(1, 2, 3).peek(appendNumbersTo(sb)).map(n -> n + 10).forEach(appendNumbersTo(sb)); IntStream.of(1, 2, 3).peek(appendIntNumbersTo(sb)).map(n -> n + 10).forEach(appendIntNumbersTo(sb));
assertEquals("1;11;2;12;3;13;", sb.toString()); assertEquals("1;11;2;12;3;13;", sb.toString());
} }
@ -185,30 +189,31 @@ public class IntStreamTest {
@Test @Test
public void streamOfOneElement() { public void streamOfOneElement() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
IntStream.of(5).forEach(appendNumbersTo(sb)); IntStream.of(5).forEach(appendIntNumbersTo(sb));
assertEquals("5;", sb.toString()); assertEquals("5;", sb.toString());
sb.setLength(0); sb.setLength(0);
IntStream.of(5).skip(1).forEach(appendNumbersTo(sb)); IntStream.of(5).skip(1).forEach(appendIntNumbersTo(sb));
assertEquals("", sb.toString()); assertEquals("", sb.toString());
sb.setLength(0); sb.setLength(0);
IntStream.concat(IntStream.of(5), IntStream.of(6)).forEach(appendNumbersTo(sb)); IntStream.concat(IntStream.of(5), IntStream.of(6)).forEach(appendIntNumbersTo(sb));
assertEquals("5;6;", sb.toString()); assertEquals("5;6;", sb.toString());
} }
@Test @Test
public void sortedStream() { public void sortedStream() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
IntStream.of(5, 7, 1, 2, 4, 3).sorted().forEach(appendNumbersTo(sb)); IntStream.of(5, 7, 1, 2, 4, 3).sorted().forEach(appendIntNumbersTo(sb));
assertEquals("1;2;3;4;5;7;", sb.toString()); assertEquals("1;2;3;4;5;7;", sb.toString());
sb.setLength(0); sb.setLength(0);
IntStream.of(2, 3, 1).peek(appendNumbersTo(sb)).sorted().limit(2).map(n -> n + 10).forEach(appendNumbersTo(sb)); IntStream.of(2, 3, 1).peek(appendIntNumbersTo(sb)).sorted().limit(2).map(n -> n + 10)
.forEach(appendIntNumbersTo(sb));
assertEquals("2;3;1;11;12;", sb.toString()); assertEquals("2;3;1;11;12;", sb.toString());
sb.setLength(0); sb.setLength(0);
IntStream.of(2, 3, 1).peek(appendNumbersTo(sb)).sorted().limit(0).forEach(appendNumbersTo(sb)); IntStream.of(2, 3, 1).peek(appendIntNumbersTo(sb)).sorted().limit(0).forEach(appendIntNumbersTo(sb));
assertEquals("2;3;1;", sb.toString()); assertEquals("2;3;1;", sb.toString());
} }
@ -287,7 +292,7 @@ public class IntStreamTest {
sb.setLength(0); sb.setLength(0);
iterator = IntStream.of(1, 2, 3).iterator(); iterator = IntStream.of(1, 2, 3).iterator();
iterator.forEachRemaining(appendNumbersTo(sb)); iterator.forEachRemaining(appendIntNumbersTo(sb));
assertEquals("1;2;3;", sb.toString()); assertEquals("1;2;3;", sb.toString());
} }
@ -295,14 +300,14 @@ public class IntStreamTest {
public void spliterator() { public void spliterator() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
Spliterator.OfInt spliterator = IntStream.of(1, 2, 3).spliterator(); Spliterator.OfInt spliterator = IntStream.of(1, 2, 3).spliterator();
while (spliterator.tryAdvance(appendNumbersTo(sb))) { while (spliterator.tryAdvance(appendIntNumbersTo(sb))) {
// continue // continue
} }
assertEquals("1;2;3;", sb.toString()); assertEquals("1;2;3;", sb.toString());
sb.setLength(0); sb.setLength(0);
spliterator = IntStream.of(1, 2, 3).spliterator(); spliterator = IntStream.of(1, 2, 3).spliterator();
spliterator.forEachRemaining(appendNumbersTo(sb)); spliterator.forEachRemaining(appendIntNumbersTo(sb));
assertEquals("1;2;3;", sb.toString()); assertEquals("1;2;3;", sb.toString());
} }
@ -315,23 +320,11 @@ public class IntStreamTest {
@Test @Test
public void range() { public void range() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
IntStream.range(1, 4).forEach(appendNumbersTo(sb)); IntStream.range(1, 4).forEach(appendIntNumbersTo(sb));
assertEquals("1;2;3;", sb.toString()); assertEquals("1;2;3;", sb.toString());
sb.setLength(0); sb.setLength(0);
IntStream.rangeClosed(1, 4).forEach(appendNumbersTo(sb)); IntStream.rangeClosed(1, 4).forEach(appendIntNumbersTo(sb));
assertEquals("1;2;3;4;", sb.toString()); 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(';');
}
} }

View File

@ -19,12 +19,13 @@ import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.teavm.classlib.java.util.stream.Helper.appendLongNumbersTo;
import static org.teavm.classlib.java.util.stream.Helper.testDoubleStream;
import static org.teavm.classlib.java.util.stream.Helper.testIntStream;
import static org.teavm.classlib.java.util.stream.Helper.testIntegerStream;
import static org.teavm.classlib.java.util.stream.Helper.testLongStream;
import java.util.PrimitiveIterator; import java.util.PrimitiveIterator;
import java.util.Spliterator; 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 java.util.stream.LongStream;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -34,85 +35,92 @@ import org.teavm.junit.TeaVMTestRunner;
public class LongStreamTest { public class LongStreamTest {
@Test @Test
public void forEachWorks() { public void forEachWorks() {
StringBuilder sb = new StringBuilder(); testLongStream(() -> LongStream.of(1, 2, 3), 1, 2, 3);
LongStream.of(1, 2, 3).forEach(appendNumbersTo(sb)); testLongStream(() -> LongStream.concat(LongStream.of(1), LongStream.of(2, 3)), 1, 2, 3);
assertEquals("1;2;3;", sb.toString()); testLongStream(() -> LongStream.concat(LongStream.empty(), LongStream.of(1, 2, 3)), 1, 2, 3);
} }
@Test @Test
public void mapWorks() { public void mapWorks() {
StringBuilder sb = new StringBuilder(); testLongStream(() -> LongStream.of(1, 2, 3).map(n -> n * n), 1, 4, 9);
LongStream.of(1, 2, 3).map(n -> n * n).forEach(appendNumbersTo(sb)); testLongStream(() -> LongStream.concat(LongStream.of(1), LongStream.of(2, 3)).map(n -> n * n), 1, 4, 9);
assertEquals("1;4;9;", sb.toString()); testLongStream(() -> LongStream.concat(LongStream.empty(), LongStream.of(1, 2, 3)).map(n -> n * n), 1, 4, 9);
} }
@Test @Test
public void mapToObjWorks() { public void mapToObjWorks() {
String result = LongStream.of(1, 2, 3).mapToObj(n -> String.valueOf(n * n)).collect(Collectors.joining(";")); testIntegerStream(() -> LongStream.of(1, 2, 3).mapToObj(n -> (int) (n * n)), 1, 4, 9);
assertEquals("1;4;9", result); testIntegerStream(() -> LongStream.concat(LongStream.of(1), LongStream.of(2, 3))
.mapToObj(n -> (int) (n * n)), 1, 4, 9);
testIntegerStream(() -> LongStream.concat(LongStream.empty(), LongStream.of(1, 2, 3))
.mapToObj(n -> (int) (n * n)), 1, 4, 9);
} }
@Test @Test
public void mapToIntWorks() { public void mapToIntWorks() {
StringBuilder sb = new StringBuilder(); testIntStream(() -> LongStream.of(1, 2, 3).mapToInt(n -> (int) (n * n)), 1, 4, 9);
LongStream.of(1, 2, 3).mapToInt(n -> (int) (n * n)).forEach(appendIntNumbersTo(sb)); testIntStream(() -> LongStream.concat(LongStream.of(1), LongStream.of(2, 3))
assertEquals("1;4;9;", sb.toString()); .mapToInt(n -> (int) (n * n)), 1, 4, 9);
testIntStream(() -> LongStream.concat(LongStream.empty(), LongStream.of(1, 2, 3))
.mapToInt(n -> (int) (n * n)), 1, 4, 9);
} }
@Test @Test
public void mapToDoubleWorks() { public void mapToDoubleWorks() {
StringBuilder sb = new StringBuilder(); testDoubleStream(() -> LongStream.of(1, 2, 3).mapToDouble(n -> n * n), 1, 4, 9);
LongStream.of(1, 2, 3).mapToDouble(n -> n * n).forEach(appendDoubleNumbersTo(sb)); testDoubleStream(() -> LongStream.concat(LongStream.of(1), LongStream.of(2, 3)).mapToDouble(n -> n * n),
assertEquals("1.0;4.0;9.0;", sb.toString()); 1, 4, 9);
testDoubleStream(() -> LongStream.concat(LongStream.empty(), LongStream.of(1, 2, 3)).mapToDouble(n -> n * n),
1, 4, 9);
} }
@Test @Test
public void filterWorks() { public void filterWorks() {
StringBuilder sb = new StringBuilder(); testLongStream(() -> LongStream.of(1, 2, 3, 4, 5, 6).filter(n -> (n & 1) == 0), 2, 4, 6);
LongStream.of(1, 2, 3, 4, 5, 6).filter(n -> (n & 1) == 0).forEach(appendNumbersTo(sb)); testLongStream(() -> LongStream.concat(LongStream.of(1), LongStream.of(2, 3, 4, 5, 6))
assertEquals("2;4;6;", sb.toString()); .filter(n -> (n & 1) == 0), 2, 4, 6);
testLongStream(() -> LongStream.concat(LongStream.empty(), LongStream.of(1, 2, 3, 4, 5, 6))
.filter(n -> (n & 1) == 0), 2, 4, 6);
} }
@Test @Test
public void flatMapWorks() { public void flatMapWorks() {
StringBuilder sb = new StringBuilder(); testLongStream(() -> LongStream.of(1, 3).flatMap(n -> LongStream.of(n, n + 1)), 1, 2, 3, 4);
LongStream.of(1, 3).flatMap(n -> LongStream.of(n, n + 1)).forEach(appendNumbersTo(sb)); testLongStream(() -> LongStream.of(1, 3).flatMap(n -> LongStream.of(n, n + 1)).skip(1), 2, 3, 4);
assertEquals("1;2;3;4;", sb.toString()); testLongStream(() -> LongStream.of(1, 4).flatMap(n -> LongStream.of(n, n + 1, n + 2)).skip(3), 4, 5, 6);
sb.setLength(0); testLongStream(() -> LongStream.of(1, 3, 100)
LongStream.of(1, 3).flatMap(n -> LongStream.of(n, n + 1)).skip(1).forEach(appendNumbersTo(sb)); .flatMap(n -> n < 100 ? LongStream.of(n, n + 1) : LongStream.empty()), 1, 2, 3, 4);
assertEquals("2;3;4;", sb.toString()); testLongStream(() -> LongStream.of(100, 1, 3)
.flatMap(n -> n < 100 ? LongStream.of(n, n + 1) : LongStream.empty()), 1, 2, 3, 4);
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 @Test
public void skipWorks() { public void skipWorks() {
for (int i = 0; i <= 6; ++i) { for (int i = 0; i <= 5; ++i) {
StringBuilder sb = new StringBuilder(); int index = i;
LongStream.iterate(1, n -> n + 1).limit(5).skip(i).forEach(appendNumbersTo(sb)); long[] expected = new long[5 - i];
StringBuilder expected = new StringBuilder();
for (int j = i; j < 5; ++j) { for (int j = i; j < 5; ++j) {
expected.append(j + 1).append(';'); expected[j - i] = j + 1;
} }
assertEquals("Error skipping " + i + " elements", expected.toString(), sb.toString()); testLongStream(() -> LongStream.iterate(1, n -> n + 1).limit(5).skip(index), expected);
testLongStream(() -> LongStream.concat(LongStream.of(1), LongStream.iterate(2, n -> n + 1).limit(4))
.skip(index), expected);
testLongStream(() -> LongStream.concat(LongStream.empty(), LongStream.iterate(1, n -> n + 1).limit(5))
.skip(index), expected);
} }
} }
@Test @Test
public void limitWorks() { public void limitWorks() {
for (int i = 0; i <= 3; ++i) { for (int i = 0; i <= 3; ++i) {
StringBuilder sb = new StringBuilder(); int index = i;
LongStream.iterate(1, n -> n + 1).limit(i).forEach(appendNumbersTo(sb)); long[] expected = new long[i];
for (int j = 0; j < expected.length; ++j) {
StringBuilder expected = new StringBuilder(); expected[j] = j + 1;
for (int j = 0; j < i; ++j) {
expected.append(j + 1).append(';');
} }
assertEquals("Error limiting to " + i + " elements", expected.toString(), sb.toString());
testLongStream(() -> LongStream.iterate(1, n -> n + 1).limit(index), expected);
} }
} }
@ -153,22 +161,22 @@ public class LongStreamTest {
@Test @Test
public void concatWorks() { public void concatWorks() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
LongStream.concat(LongStream.of(1, 2), LongStream.of(3, 4)).forEach(appendNumbersTo(sb)); LongStream.concat(LongStream.of(1, 2), LongStream.of(3, 4)).forEach(appendLongNumbersTo(sb));
assertEquals("1;2;3;4;", sb.toString()); assertEquals("1;2;3;4;", sb.toString());
sb.setLength(0); sb.setLength(0);
LongStream.concat(LongStream.of(1, 2), LongStream.of(3, 4)).skip(1).forEach(appendNumbersTo(sb)); LongStream.concat(LongStream.of(1, 2), LongStream.of(3, 4)).skip(1).forEach(appendLongNumbersTo(sb));
assertEquals("2;3;4;", sb.toString()); assertEquals("2;3;4;", sb.toString());
sb.setLength(0); sb.setLength(0);
LongStream.concat(LongStream.of(1, 2), LongStream.of(3, 4, 5)).skip(3).forEach(appendNumbersTo(sb)); LongStream.concat(LongStream.of(1, 2), LongStream.of(3, 4, 5)).skip(3).forEach(appendLongNumbersTo(sb));
assertEquals("4;5;", sb.toString()); assertEquals("4;5;", sb.toString());
} }
@Test @Test
public void peekWorks() { public void peekWorks() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
LongStream.of(1, 2, 3).peek(appendNumbersTo(sb)).map(n -> n + 10).forEach(appendNumbersTo(sb)); LongStream.of(1, 2, 3).peek(appendLongNumbersTo(sb)).map(n -> n + 10).forEach(appendLongNumbersTo(sb));
assertEquals("1;11;2;12;3;13;", sb.toString()); assertEquals("1;11;2;12;3;13;", sb.toString());
} }
@ -185,31 +193,31 @@ public class LongStreamTest {
@Test @Test
public void streamOfOneElement() { public void streamOfOneElement() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
LongStream.of(5).forEach(appendNumbersTo(sb)); LongStream.of(5).forEach(appendLongNumbersTo(sb));
assertEquals("5;", sb.toString()); assertEquals("5;", sb.toString());
sb.setLength(0); sb.setLength(0);
LongStream.of(5).skip(1).forEach(appendNumbersTo(sb)); LongStream.of(5).skip(1).forEach(appendLongNumbersTo(sb));
assertEquals("", sb.toString()); assertEquals("", sb.toString());
sb.setLength(0); sb.setLength(0);
LongStream.concat(LongStream.of(5), LongStream.of(6)).forEach(appendNumbersTo(sb)); LongStream.concat(LongStream.of(5), LongStream.of(6)).forEach(appendLongNumbersTo(sb));
assertEquals("5;6;", sb.toString()); assertEquals("5;6;", sb.toString());
} }
@Test @Test
public void sortedStream() { public void sortedStream() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
LongStream.of(5, 7, 1, 2, 4, 3).sorted().forEach(appendNumbersTo(sb)); LongStream.of(5, 7, 1, 2, 4, 3).sorted().forEach(appendLongNumbersTo(sb));
assertEquals("1;2;3;4;5;7;", sb.toString()); assertEquals("1;2;3;4;5;7;", sb.toString());
sb.setLength(0); sb.setLength(0);
LongStream.of(2, 3, 1).peek(appendNumbersTo(sb)).sorted().limit(2).map(n -> n + 10) LongStream.of(2, 3, 1).peek(appendLongNumbersTo(sb)).sorted().limit(2).map(n -> n + 10)
.forEach(appendNumbersTo(sb)); .forEach(appendLongNumbersTo(sb));
assertEquals("2;3;1;11;12;", sb.toString()); assertEquals("2;3;1;11;12;", sb.toString());
sb.setLength(0); sb.setLength(0);
LongStream.of(2, 3, 1).peek(appendNumbersTo(sb)).sorted().limit(0).forEach(appendNumbersTo(sb)); LongStream.of(2, 3, 1).peek(appendLongNumbersTo(sb)).sorted().limit(0).forEach(appendLongNumbersTo(sb));
assertEquals("2;3;1;", sb.toString()); assertEquals("2;3;1;", sb.toString());
} }
@ -288,7 +296,7 @@ public class LongStreamTest {
sb.setLength(0); sb.setLength(0);
iterator = LongStream.of(1, 2, 3).iterator(); iterator = LongStream.of(1, 2, 3).iterator();
iterator.forEachRemaining(appendNumbersTo(sb)); iterator.forEachRemaining(appendLongNumbersTo(sb));
assertEquals("1;2;3;", sb.toString()); assertEquals("1;2;3;", sb.toString());
} }
@ -296,14 +304,14 @@ public class LongStreamTest {
public void spliterator() { public void spliterator() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
Spliterator.OfLong spliterator = LongStream.of(1, 2, 3).spliterator(); Spliterator.OfLong spliterator = LongStream.of(1, 2, 3).spliterator();
while (spliterator.tryAdvance(appendNumbersTo(sb))) { while (spliterator.tryAdvance(appendLongNumbersTo(sb))) {
// continue // continue
} }
assertEquals("1;2;3;", sb.toString()); assertEquals("1;2;3;", sb.toString());
sb.setLength(0); sb.setLength(0);
spliterator = LongStream.of(1, 2, 3).spliterator(); spliterator = LongStream.of(1, 2, 3).spliterator();
spliterator.forEachRemaining(appendNumbersTo(sb)); spliterator.forEachRemaining(appendLongNumbersTo(sb));
assertEquals("1;2;3;", sb.toString()); assertEquals("1;2;3;", sb.toString());
} }
@ -316,23 +324,11 @@ public class LongStreamTest {
@Test @Test
public void range() { public void range() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
LongStream.range(1, 4).forEach(appendNumbersTo(sb)); LongStream.range(1, 4).forEach(appendLongNumbersTo(sb));
assertEquals("1;2;3;", sb.toString()); assertEquals("1;2;3;", sb.toString());
sb.setLength(0); sb.setLength(0);
LongStream.rangeClosed(1, 4).forEach(appendNumbersTo(sb)); LongStream.rangeClosed(1, 4).forEach(appendLongNumbersTo(sb));
assertEquals("1;2;3;4;", sb.toString()); 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(';');
}
} }

View File

@ -19,14 +19,15 @@ import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.teavm.classlib.java.util.stream.Helper.appendNumbersTo;
import static org.teavm.classlib.java.util.stream.Helper.testDoubleStream;
import static org.teavm.classlib.java.util.stream.Helper.testIntStream;
import static org.teavm.classlib.java.util.stream.Helper.testIntegerStream;
import static org.teavm.classlib.java.util.stream.Helper.testLongStream;
import java.util.Comparator; import java.util.Comparator;
import java.util.Iterator; import java.util.Iterator;
import java.util.Spliterator; import java.util.Spliterator;
import java.util.function.Consumer;
import java.util.function.DoubleConsumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.IntConsumer;
import java.util.function.LongConsumer;
import java.util.stream.DoubleStream; import java.util.stream.DoubleStream;
import java.util.stream.IntStream; import java.util.stream.IntStream;
import java.util.stream.LongStream; import java.util.stream.LongStream;
@ -39,137 +40,139 @@ import org.teavm.junit.TeaVMTestRunner;
public class StreamTest { public class StreamTest {
@Test @Test
public void forEachWorks() { public void forEachWorks() {
StringBuilder sb = new StringBuilder(); testIntegerStream(() -> Stream.of(1, 2, 3), 1, 2, 3);
Stream.of(1, 2, 3).forEach(appendNumbersTo(sb)); testIntegerStream(() -> Stream.concat(Stream.of(1), Stream.of(2, 3)), 1, 2, 3);
assertEquals("1;2;3;", sb.toString()); testIntegerStream(() -> Stream.concat(Stream.empty(), Stream.of(1, 2, 3)), 1, 2, 3);
} }
@Test @Test
public void mapWorks() { public void mapWorks() {
StringBuilder sb = new StringBuilder(); testIntegerStream(() -> Stream.of(1, 2, 3).map(n -> n * n), 1, 4, 9);
Stream.of(1, 2, 3).map(n -> n * n).forEach(appendNumbersTo(sb)); testIntegerStream(() -> Stream.concat(Stream.of(1), Stream.of(2, 3)).map(n -> n * n), 1, 4, 9);
assertEquals("1;4;9;", sb.toString()); testIntegerStream(() -> Stream.concat(Stream.empty(), Stream.of(1, 2, 3)).map(n -> n * n), 1, 4, 9);
} }
@Test @Test
public void mapToIntWorks() { public void mapToIntWorks() {
StringBuilder sb = new StringBuilder(); testIntStream(() -> Stream.of(1, 2, 3).mapToInt(n -> n * n), 1, 4, 9);
Stream.of(1, 2, 3).mapToInt(n -> n * n).forEach(appendIntNumbersTo(sb)); testIntStream(() -> Stream.concat(Stream.of(1), Stream.of(2, 3)).mapToInt(n -> n * n), 1, 4, 9);
assertEquals("1;4;9;", sb.toString()); testIntStream(() -> Stream.concat(Stream.empty(), Stream.of(1, 2, 3)).mapToInt(n -> n * n), 1, 4, 9);
} }
@Test @Test
public void mapToLongWorks() { public void mapToLongWorks() {
StringBuilder sb = new StringBuilder(); testLongStream(() -> Stream.of(1, 2, 3).mapToLong(n -> n * n), 1, 4, 9);
Stream.of(1, 2, 3).mapToLong(n -> n * n).forEach(appendLongNumbersTo(sb)); testLongStream(() -> Stream.concat(Stream.of(1), Stream.of(2, 3)).mapToLong(n -> n * n), 1, 4, 9);
assertEquals("1;4;9;", sb.toString()); testLongStream(() -> Stream.concat(Stream.empty(), Stream.of(1, 2, 3)).mapToLong(n -> n * n), 1, 4, 9);
} }
@Test @Test
public void mapToDoubleWorks() { public void mapToDoubleWorks() {
StringBuilder sb = new StringBuilder(); testDoubleStream(() -> Stream.of(1, 2, 3).mapToDouble(n -> n * n), 1, 4, 9);
Stream.of(1, 2, 3).mapToDouble(n -> n * n).forEach(appendDoubleNumbersTo(sb)); testDoubleStream(() -> Stream.concat(Stream.of(1), Stream.of(2, 3)).mapToDouble(n -> n * n), 1, 4, 9);
assertEquals("1.0;4.0;9.0;", sb.toString()); testDoubleStream(() -> Stream.concat(Stream.empty(), Stream.of(1, 2, 3)).mapToDouble(n -> n * n), 1, 4, 9);
} }
@Test @Test
public void filterWorks() { public void filterWorks() {
StringBuilder sb = new StringBuilder(); testIntegerStream(() -> Stream.of(1, 2, 3, 4, 5, 6).filter(n -> (n & 1) == 0), 2, 4, 6);
Stream.of(1, 2, 3, 4, 5, 6).filter(n -> (n & 1) == 0).forEach(appendNumbersTo(sb)); testIntegerStream(() -> Stream.concat(Stream.of(1), Stream.of(2, 3, 4, 5, 6)).filter(n -> (n & 1) == 0),
assertEquals("2;4;6;", sb.toString()); 2, 4, 6);
testIntegerStream(() -> Stream.concat(Stream.empty(), Stream.of(1, 2, 3, 4, 5, 6)).filter(n -> (n & 1) == 0),
2, 4, 6);
} }
@Test @Test
public void flatMapWorks() { public void flatMapWorks() {
StringBuilder sb = new StringBuilder(); testIntegerStream(() -> Stream.of(Stream.of(1, 2), Stream.of(3, 4)).flatMap(n -> n), 1, 2, 3, 4);
Stream.of(Stream.of(1, 2), Stream.of(3, 4)).flatMap(n -> n).forEach(appendNumbersTo(sb)); testIntegerStream(() -> Stream.of(Stream.<Integer>empty(), Stream.of(1, 2), Stream.of(3, 4)).flatMap(n -> n),
assertEquals("1;2;3;4;", sb.toString()); 1, 2, 3, 4);
testIntegerStream(() -> Stream.of(Stream.of(1, 2), Stream.<Integer>empty(), Stream.of(3, 4)).flatMap(n -> n),
1, 2, 3, 4);
testIntegerStream(() -> Stream.of(Stream.of(1, 2), Stream.of(3, 4), Stream.<Integer>empty()).flatMap(n -> n),
1, 2, 3, 4);
sb.setLength(0); testIntegerStream(() -> Stream.of(Stream.of(1, 2), Stream.of(3, 4)).flatMap(n -> n).skip(1), 2, 3, 4);
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); testIntegerStream(() -> Stream.of(Stream.of(1, 2), Stream.of(3, 4, 5)).flatMap(n -> n).skip(3), 4, 5);
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 @Test
public void flatMapToIntWorks() { public void flatMapToIntWorks() {
StringBuilder sb = new StringBuilder(); testIntStream(() -> Stream.of(IntStream.of(1, 2), IntStream.of(3, 4)).flatMapToInt(n -> n), 1, 2, 3, 4);
Stream.of(IntStream.of(1, 2), IntStream.of(3, 4)).flatMapToInt(n -> n).forEach(appendIntNumbersTo(sb)); testIntStream(() -> Stream.of(IntStream.empty(), IntStream.of(1, 2), IntStream.of(3, 4)).flatMapToInt(n -> n),
assertEquals("1;2;3;4;", sb.toString()); 1, 2, 3, 4);
testIntStream(() -> Stream.of(IntStream.of(1, 2), IntStream.empty(), IntStream.of(3, 4)).flatMapToInt(n -> n),
1, 2, 3, 4);
testIntStream(() -> Stream.of(IntStream.of(1, 2), IntStream.of(3, 4), IntStream.empty()).flatMapToInt(n -> n),
1, 2, 3, 4);
sb.setLength(0); testIntStream(() -> Stream.of(IntStream.of(1, 2), IntStream.of(3, 4)).flatMapToInt(n -> n).skip(1), 2, 3, 4);
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); testIntStream(() -> Stream.of(IntStream.of(1, 2), IntStream.of(3, 4, 5)).flatMapToInt(n -> n).skip(3), 4, 5);
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 @Test
public void flatMapToLongWorks() { public void flatMapToLongWorks() {
StringBuilder sb = new StringBuilder(); testLongStream(() -> Stream.of(LongStream.of(1, 2), LongStream.of(3, 4)).flatMapToLong(n -> n), 1, 2, 3, 4);
Stream.of(LongStream.of(1, 2), LongStream.of(3, 4)).flatMapToLong(n -> n).forEach(appendLongNumbersTo(sb)); testLongStream(() -> Stream.of(LongStream.empty(), LongStream.of(1, 2), LongStream.of(3, 4))
assertEquals("1;2;3;4;", sb.toString()); .flatMapToLong(n -> n), 1, 2, 3, 4);
testLongStream(() -> Stream.of(LongStream.of(1, 2), LongStream.empty(), LongStream.of(3, 4))
.flatMapToLong(n -> n), 1, 2, 3, 4);
testLongStream(() -> Stream.of(LongStream.of(1, 2), LongStream.of(3, 4), LongStream.empty())
.flatMapToLong(n -> n), 1, 2, 3, 4);
sb.setLength(0); testLongStream(() -> Stream.of(LongStream.of(1, 2), LongStream.of(3, 4))
Stream.of(LongStream.of(1, 2), LongStream.of(3, 4)).flatMapToLong(n -> n).skip(1) .flatMapToLong(n -> n).skip(1), 2, 3, 4);
.forEach(appendLongNumbersTo(sb));
assertEquals("2;3;4;", sb.toString());
sb.setLength(0); testLongStream(() -> Stream.of(LongStream.of(1, 2), LongStream.of(3, 4, 5))
Stream.of(LongStream.of(1, 2), LongStream.of(3, 4, 5)).flatMapToLong(n -> n).skip(3) .flatMapToLong(n -> n).skip(3), 4, 5);
.forEach(appendLongNumbersTo(sb));
assertEquals("4;5;", sb.toString());
} }
@Test @Test
public void flatMapToDoubleWorks() { public void flatMapToDoubleWorks() {
StringBuilder sb = new StringBuilder(); testDoubleStream(() -> Stream.of(DoubleStream.of(1, 2), DoubleStream.of(3, 4)).flatMapToDouble(n -> n),
Stream.of(DoubleStream.of(1, 2), DoubleStream.of(3, 4)).flatMapToDouble(n -> n) 1, 2, 3, 4);
.forEach(appendDoubleNumbersTo(sb)); testDoubleStream(() -> Stream.of(DoubleStream.empty(), DoubleStream.of(1, 2), DoubleStream.of(3, 4))
assertEquals("1.0;2.0;3.0;4.0;", sb.toString()); .flatMapToDouble(n -> n), 1, 2, 3, 4);
testDoubleStream(() -> Stream.of(DoubleStream.of(1, 2), DoubleStream.empty(), DoubleStream.of(3, 4))
.flatMapToDouble(n -> n), 1, 2, 3, 4);
testDoubleStream(() -> Stream.of(DoubleStream.of(1, 2), DoubleStream.of(3, 4), DoubleStream.empty())
.flatMapToDouble(n -> n), 1, 2, 3, 4);
sb.setLength(0); testDoubleStream(() -> Stream.of(DoubleStream.of(1, 2), DoubleStream.of(3, 4))
Stream.of(DoubleStream.of(1, 2), DoubleStream.of(3, 4)).flatMapToDouble(n -> n).skip(1) .flatMapToDouble(n -> n).skip(1), 2, 3, 4);
.forEach(appendDoubleNumbersTo(sb));
assertEquals("2.0;3.0;4.0;", sb.toString());
sb.setLength(0); testDoubleStream(() -> Stream.of(DoubleStream.of(1, 2), DoubleStream.of(3, 4, 5))
Stream.of(DoubleStream.of(1, 2), DoubleStream.of(3, 4, 5)).flatMapToDouble(n -> n).skip(3) .flatMapToDouble(n -> n).skip(3), 4, 5);
.forEach(appendDoubleNumbersTo(sb));
assertEquals("4.0;5.0;", sb.toString());
} }
@Test @Test
public void skipWorks() { public void skipWorks() {
for (int i = 0; i <= 6; ++i) { for (int i = 0; i <= 5; ++i) {
StringBuilder sb = new StringBuilder(); int index = i;
Stream.iterate(1, n -> n + 1).limit(5).skip(i).forEach(appendNumbersTo(sb)); Integer[] expected = new Integer[5 - i];
StringBuilder expected = new StringBuilder();
for (int j = i; j < 5; ++j) { for (int j = i; j < 5; ++j) {
expected.append(j + 1).append(';'); expected[j - i] = j + 1;
} }
assertEquals("Error skipping " + i + " elements", expected.toString(), sb.toString()); testIntegerStream(() -> Stream.iterate(1, n -> n + 1).limit(5).skip(index), expected);
testIntegerStream(() -> Stream.concat(Stream.of(1), Stream.iterate(2, n -> n + 1).limit(4))
.skip(index), expected);
testIntegerStream(() -> Stream.concat(Stream.empty(), Stream.iterate(1, n -> n + 1).limit(5))
.skip(index), expected);
} }
} }
@Test @Test
public void limitWorks() { public void limitWorks() {
for (int i = 0; i <= 3; ++i) { for (int i = 0; i <= 3; ++i) {
StringBuilder sb = new StringBuilder(); int index = i;
Stream.iterate(1, n -> n + 1).limit(i).forEach(appendNumbersTo(sb)); Integer[] expected = new Integer[i];
for (int j = 0; j < expected.length; ++j) {
StringBuilder expected = new StringBuilder(); expected[j] = j + 1;
for (int j = 0; j < i; ++j) {
expected.append(j + 1).append(';');
} }
assertEquals("Error limiting to " + i + " elements", expected.toString(), sb.toString());
testIntegerStream(() -> Stream.iterate(1, n -> n + 1).limit(index), expected);
} }
} }
@ -242,26 +245,20 @@ public class StreamTest {
@Test @Test
public void streamOfOneElement() { public void streamOfOneElement() {
StringBuilder sb = new StringBuilder(); testIntegerStream(() -> Stream.of(5), 5);
Stream.of(5).forEach(appendNumbersTo(sb)); testIntegerStream(() -> Stream.of(5).skip(1));
assertEquals("5;", sb.toString()); testIntegerStream(() -> Stream.concat(Stream.of(5), Stream.of(6)), 5, 6);
testIntegerStream(() -> Stream.concat(Stream.empty(), Stream.of(5)), 5);
sb.setLength(0); testIntegerStream(() -> Stream.concat(Stream.of(5), Stream.empty()), 5);
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 @Test
public void sortedStream() { public void sortedStream() {
StringBuilder sb = new StringBuilder(); testIntegerStream(() -> Stream.of(5, 7, 1, 2, 4, 3).sorted(), 1, 2, 3, 4, 5, 7);
Stream.of(5, 7, 1, 2, 4, 3).sorted().forEach(appendNumbersTo(sb)); testIntegerStream(() -> Stream.concat(Stream.of(5), Stream.of(7, 1, 2, 4, 3)).sorted(), 1, 2, 3, 4, 5, 7);
assertEquals("1;2;3;4;5;7;", sb.toString()); testIntegerStream(() -> Stream.concat(Stream.empty(), Stream.of(5, 7, 1, 2, 4, 3)).sorted(), 1, 2, 3, 4, 5, 7);
sb.setLength(0); StringBuilder sb = new StringBuilder();
Stream.of(2, 3, 1).peek(appendNumbersTo(sb)).sorted().limit(2).map(n -> n + 10).forEach(appendNumbersTo(sb)); 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()); assertEquals("2;3;1;11;12;", sb.toString());
@ -367,20 +364,4 @@ public class StreamTest {
spliterator.forEachRemaining(appendNumbersTo(sb)); spliterator.forEachRemaining(appendNumbersTo(sb));
assertEquals("1;2;3;", sb.toString()); assertEquals("1;2;3;", sb.toString());
} }
}
private Consumer<Integer> 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(';');
}
}