T
- the type of the stream elementsA
- the type of arrayP
- the type of predicateC
- the type of consumerPL
- the type of PrimitiveList/ListOT
- the type of OptionalIT
- the type of IndexedITER
- the type of IteratorS
- the type of of the stream implementing BaseStream
public interface BaseStream<T,A,P,C,PL,OT,IT,ITER,S extends BaseStream<T,A,P,C,PL,OT,IT,ITER,S>>
extends java.lang.AutoCloseable
Stream
,
IntStream
,
LongStream
,
DoubleStream
Modifier and Type | Interface and Description |
---|---|
static class |
BaseStream.Splitor |
Modifier and Type | Method and Description |
---|---|
<R> R |
__(Function<? super S,R> transfer) |
S |
append(S s) |
S |
appendIfEmpty(Supplier<S> suppliers) |
S |
carry(C action)
Same as
peek |
void |
close() |
long |
count() |
S |
difference(java.util.Collection<?> c)
This method only run sequentially, even in parallel stream. |
S |
distinct()
Returns a stream consisting of the distinct elements of this stream.
|
S |
dropWhile(P predicate)
Remove the elements until the given predicate returns false.
|
S |
dropWhile(P predicate,
C consumer)
Remove the elements until the given predicate returns false.
|
S |
filter(P predicate)
Returns a stream consisting of the elements of this stream that match the given predicate.
|
OT |
first() |
Stream<IT> |
indexed()
This method only run sequentially, even in parallel stream. |
S |
intersection(java.util.Collection<?> c)
This method only run sequentially, even in parallel stream. |
boolean |
isParallel() |
ITER |
iterator()
Returns an iterator for the elements of this stream.
|
java.lang.String |
join(java.lang.CharSequence delimiter) |
java.lang.String |
join(java.lang.CharSequence delimiter,
java.lang.CharSequence prefix,
java.lang.CharSequence suffix) |
OT |
last() |
S |
limit(long maxSize) |
S |
onClose(java.lang.Runnable closeHandler) |
OT |
onlyOne() |
S |
parallel() |
S |
parallel(BaseStream.Splitor splitor) |
S |
parallel(java.util.concurrent.Executor executor) |
S |
parallel(int maxThreadNum) |
S |
parallel(int maxThreadNum,
BaseStream.Splitor splitor)
Returns an equivalent stream that is parallel.
|
S |
parallel(int maxThreadNum,
java.util.concurrent.Executor executor) |
S |
peek(C action) |
u.Optional<java.util.Map<com.landawn.abacus.util.Percentage,T>> |
percentiles()
All elements will be loaded to memory and sorted if not yet. |
S |
prepend(S stream) |
void |
println() |
S |
removeIf(P predicate) |
S |
removeIf(P predicate,
C consumer) |
S |
reversed()
This method only run sequentially, even in parallel stream and all elements will be loaded to memory. |
S |
reverseSorted() |
S |
rotated(int distance)
This method only run sequentially, even in parallel stream and all elements will be loaded to memory. |
S |
sequential() |
S |
shuffled()
This method only run sequentially, even in parallel stream and all elements will be loaded to memory. |
S |
shuffled(java.util.Random rnd)
This method only run sequentially, even in parallel stream and all elements will be loaded to memory. |
S |
skip(long n) |
S |
skip(long n,
C consumer) |
S |
slice(long from,
long to)
Same as:
stream.skip(from).limit(to - from) . |
Stream<S> |
sliding(int windowSize) |
Stream<S> |
sliding(int windowSize,
int increment)
Stream.of(1, 2, 3, 4, 5, 6, 7, 8).sliding(3, 1).forEach(Stream::println)
output: [1, 2, 3] [2, 3, 4] [3, 4, 5] [4, 5, 6] [5, 6, 7] [6, 7, 8] ============================================================================ Stream.of(1, 2, 3, 4, 5, 6, 7, 8).sliding(3, 3).forEach(Stream::println)
output: [1, 2, 3] [4, 5, 6] [7, 8] ============================================================================ Stream.of(1, 2, 3, 4, 5, 6, 7, 5).sliding(3, 5).forEach(Stream::println)
output: [1, 2, 3] [6, 7, 8] This method only run sequentially, even in parallel stream. |
Stream<PL> |
slidingToList(int windowSize) |
Stream<PL> |
slidingToList(int windowSize,
int increment) |
S |
sorted()
Returns a stream consisting of the elements of this stream in sorted order.
|
Stream<S> |
split(int size)
Returns Stream of
S with consecutive sub sequences of the elements, each of the same size (the final sequence may be smaller). |
Stream<S> |
split(P predicate)
Split the stream by the specified predicate.
|
Stream<S> |
splitAt(int where)
Split the stream into two pieces at
where . |
Stream<S> |
splitBy(P where)
Split the stream into two pieces at
where turns to false
The first piece will be loaded into memory. |
Stream<PL> |
splitToList(int size)
Returns Stream of
PL with consecutive sub sequences of the elements, each of the same size (the final sequence may be smaller). |
Stream<PL> |
splitToList(P predicate)
Split the stream by the specified predicate.
|
S |
step(long step) |
S |
symmetricDifference(java.util.Collection<T> c)
This method only run sequentially, even in parallel stream. |
S |
takeWhile(P predicate)
Keep the elements until the given predicate returns false.
|
A |
toArray() |
<CC extends java.util.Collection<T>> |
toCollection(Supplier<? extends CC> supplier) |
ImmutableList<T> |
toImmutableList() |
ImmutableSet<T> |
toImmutableSet() |
java.util.List<T> |
toList() |
LongMultiset<T> |
toLongMultiset() |
LongMultiset<T> |
toLongMultiset(Supplier<? extends LongMultiset<T>> supplier) |
Multiset<T> |
toMultiset() |
Multiset<T> |
toMultiset(Supplier<? extends Multiset<T>> supplier) |
java.util.Set<T> |
toSet() |
@ParallelSupported S filter(P predicate)
predicate
- @ParallelSupported S takeWhile(P predicate)
predicate.text(x)
returns false, any element y behind x: predicate.text(y)
should returns false.
In parallel Streams, the elements after the first element which predicate
returns false may be tested by predicate too.predicate
- @ParallelSupported S dropWhile(P predicate)
predicate.text(x)
returns true, any element y behind x: predicate.text(y)
should returns true.
In parallel Streams, the elements after the first element which predicate
returns false may be tested by predicate too.predicate
- @ParallelSupported S dropWhile(P predicate, C consumer)
predicate.text(x)
returns true, any element y behind x: predicate.text(y)
should returns true.
In parallel Streams, the elements after the first element which predicate
returns false may be tested by predicate too.predicate
- consumer
- @SequentialOnly Stream<S> split(int size)
S
with consecutive sub sequences of the elements, each of the same size (the final sequence may be smaller).size
- @SequentialOnly Stream<PL> splitToList(int size)
PL
with consecutive sub sequences of the elements, each of the same size (the final sequence may be smaller).
size
- @SequentialOnly Stream<S> split(P predicate)
predicate
- @SequentialOnly Stream<PL> splitToList(P predicate)
predicate
- @SequentialOnly Stream<S> splitAt(int where)
where
.
The first piece will be loaded into memory.where
- @ParallelSupported Stream<S> splitBy(P where)
where
turns to false
The first piece will be loaded into memory.
Stream.of(1, 3, 2, 4, 2, 5).splitBy(i -> i <= 3).forEach(s -> s.println()); // [1, 3, 2], [4, 2, 5]
where
- @SequentialOnly Stream<S> sliding(int windowSize)
windowSize
- sliding(int, int)
@SequentialOnly Stream<PL> slidingToList(int windowSize)
windowSize
- sliding(int, int)
@SequentialOnly Stream<S> sliding(int windowSize, int increment)
Stream.of(1, 2, 3, 4, 5, 6, 7, 8).sliding(3, 1).forEach(Stream::println)
Stream.of(1, 2, 3, 4, 5, 6, 7, 8).sliding(3, 3).forEach(Stream::println)
Stream.of(1, 2, 3, 4, 5, 6, 7, 5).sliding(3, 5).forEach(Stream::println)
windowSize
- increment
- @SequentialOnly Stream<PL> slidingToList(int windowSize, int increment)
windowSize
- increment
- sliding(int, int)
@SequentialOnly S intersection(java.util.Collection<?> c)
c
- IntList.intersection(IntList)
@SequentialOnly S difference(java.util.Collection<?> c)
c
- IntList.difference(IntList)
@SequentialOnly S symmetricDifference(java.util.Collection<T> c)
c
- IntList.symmetricDifference(IntList)
@SequentialOnly u.Optional<java.util.Map<com.landawn.abacus.util.Percentage,T>> percentiles()
@SequentialOnly S reversed()
@SequentialOnly S shuffled()
@SequentialOnly S shuffled(java.util.Random rnd)
@SequentialOnly S rotated(int distance)
@SequentialOnly S distinct()
@ParallelSupported S sorted()
@ParallelSupported S reverseSorted()
@SequentialOnly Stream<IT> indexed()
@SequentialOnly java.lang.String join(java.lang.CharSequence delimiter)
@SequentialOnly java.lang.String join(java.lang.CharSequence delimiter, java.lang.CharSequence prefix, java.lang.CharSequence suffix)
@SequentialOnly S skip(long n)
n
- @SequentialOnly S limit(long maxSize)
maxSize
- @SequentialOnly S slice(long from, long to)
stream.skip(from).limit(to - from)
.from
- to
- @SequentialOnly S step(long step)
@SequentialOnly long count()
@ParallelSupported S carry(C action)
peek
action
- peek(Object)
@SequentialOnly OT first()
@SequentialOnly OT last()
@SequentialOnly OT onlyOne() throws DuplicatedResultException
DuplicatedResultException
- if there are more than one element in this stream.@SequentialOnly A toArray()
@SequentialOnly java.util.List<T> toList()
@SequentialOnly java.util.Set<T> toSet()
@SequentialOnly ImmutableList<T> toImmutableList()
@SequentialOnly ImmutableSet<T> toImmutableSet()
@SequentialOnly <CC extends java.util.Collection<T>> CC toCollection(Supplier<? extends CC> supplier)
@SequentialOnly LongMultiset<T> toLongMultiset()
@SequentialOnly LongMultiset<T> toLongMultiset(Supplier<? extends LongMultiset<T>> supplier)
@SequentialOnly ITER iterator()
@Beta @SequentialOnly void println()
@SequentialOnly S onClose(java.lang.Runnable closeHandler)
closeHandler
- @SequentialOnly void close()
close
in interface java.lang.AutoCloseable
boolean isParallel()
S sequential()
S parallel()
S parallel(int maxThreadNum)
maxThreadNum
- S parallel(BaseStream.Splitor splitor)
splitor
- S parallel(int maxThreadNum, BaseStream.Splitor splitor)
maxThreadNum
and splitor
as the specified ones.
Profiler.run(1, 1, 3, "sequential", () -> Stream.of(list).operation(F)...).printResult();
Profiler.run(1, 1, 3, "parallel", () -> Stream.of(list).parallel().operation(F)...).printResult();
Here is a sample performance test with computer: CPU Intel i7-3520M 4-cores 2.9 GHz, JDK 1.8.0_101, Windows 7:
public void test_perf() {
final String[] strs = new String[10_000];
N.fill(strs, N.uuid());
final int m = 1;
final Function mapper = str -> {
long result = 0;
for (int i = 0; i < m; i++) {
result += sum(str.toCharArray()) + 1;
}
return result;
};
final MutableLong sum = MutableLong.of(0);
for (int i = 0, len = strs.length; i < len; i++) {
sum.add(mapper.apply(strs[i]));
}
final int threadNum = 1, loopNum = 100, roundNum = 3;
Profiler.run(threadNum, loopNum, roundNum, "For Loop", () -> {
long result = 0;
for (int i = 0, len = strs.length; i < len; i++) {
result += mapper.apply(strs[i]);
}
assertEquals(sum.longValue(), result);
}).printResult();
Profiler.run(threadNum, loopNum, roundNum, "JDK Sequential",
() -> assertEquals(sum.longValue(), java.util.stream.Stream.of(strs).map(mapper).mapToLong(e -> e).sum())).printResult();
Profiler.run(threadNum, loopNum, roundNum, "JDK Parallel",
() -> assertEquals(sum.longValue(), java.util.stream.Stream.of(strs).parallel().map(mapper).mapToLong(e -> e).sum())).printResult();
Profiler.run(threadNum, loopNum, roundNum, "Abcus Sequential",
() -> assertEquals(sum.longValue(), Stream.of(strs).map(mapper).mapToLong(e -> e).sum().longValue())).printResult();
Profiler.run(threadNum, loopNum, roundNum, "Abcus Parallel",
() -> assertEquals(sum.longValue(), Stream.of(strs).parallel().map(mapper).mapToLong(e -> e).sum().longValue())).printResult();
}
And test result: Unit is milliseconds. N(the number of elements) is 10_000, Q(cost per element of F, the per-element function (usually a lambda), here is mapper
) is calculated by: value of 'For loop' / N(10_000).
m = 1 | m = 10 | m = 50 | m = 100 | m = 500 | m = 1000 | |
---|---|---|---|---|---|---|
Q | 0.00002 | 0.0002 | 0.001 | 0.002 | 0.01 | 0.02 |
For Loop | 0.23 | 2.3 | 11 | 22 | 110 | 219 |
JDK Sequential | 0.28 | 2.3 | 11 | 22 | 114 | 212 |
JDK Parallel | 0.22 | 1.3 | 6 | 12 | 66 | 122 |
Abcus Sequential | 0.3 | 2 | 11 | 22 | 112 | 212 |
Abcus Parallel | 11 | 11 | 11 | 16 | 77 | 128 |
f = (int a, int b) -> a + b;
.
But if we look into the samples in the article and think about it: it just takes less than 1 milliseconds to get the max value in 100k numbers.
There is potential performance issue only if the "get the max value in 100K numbers" call many, many times in your API or single request.
Otherwise, the difference between 0.1 milliseconds to 0.5 milliseconds can be totally ignored.
Usually we meet performance issue only if Q and F is big enough. However, the performance of Lambdas/Streams APIs is closed to for loop when Q and F is big enough.
No matter in which scenario, We don't need and should not concern the performance of Lambdas/Stream APIs.
maxThreadNum
- Default value is the number of cpu-cores. Steps/operations will be executed sequentially if maxThreadNum
is 1.splitor
- The target array is split by ranges for multiple threads if splitor is splitor.ARRAY
and target stream composed by array. It looks like:
for (int i = 0; i < maxThreadNum; i++) {
final int sliceIndex = i;
futureList.add(asyncExecutor.execute(new Runnable() {
public void run() {
int cursor = fromIndex + sliceIndex * sliceSize;
final int to = toIndex - cursor > sliceSize ? cursor + sliceSize : toIndex;
while (cursor < to) {
action.accept(elements[cursor++]);
}
}
}));
}
Otherwise, each thread will get the elements from the target array/iterator in the stream one by one with the target array/iterator synchronized. It looks like:
for (int i = 0; i < maxThreadNum; i++) {
futureList.add(asyncExecutor.execute(new Runnable() {
public void run() {
T next = null;
while (true) {
synchronized (elements) {
if (cursor.intValue() < toIndex) {
next = elements[cursor.getAndIncrement()];
} else {
break;
}
}
action.accept(next);
}
}
}));
}
Using splitor.ARRAY
only when F (the per-element function (usually a lambda)) is very tiny and the cost of synchronization on the target array/iterator is too big to it.
For the F involving IO or taking 'long' to complete, choose splitor.ITERATOR
. Default value is splitor.ITERATOR
.Nth
,
com.landawn.abacus.util.Profiler#run(int, int, int, String, Runnable)
,
Understanding Parallel Stream Performance in Java SE 8,
When to use parallel StreamsS parallel(int maxThreadNum, java.util.concurrent.Executor executor)
maxThreadNum
- executor
- should be able to execute sum of maxThreadNum
operations in parallel.S parallel(java.util.concurrent.Executor executor)
executor
- should be able to execute sum of maxThreadNum
operations in parallel.