Lazy and fast concat and prepend (#30252)
This commit is contained in:
parent
cbb12e6ef3
commit
4ade8ef2d1
17 changed files with 825 additions and 77 deletions
|
|
@ -14,6 +14,17 @@ After completion of the original upstream the elements of the given source will
|
|||
|
||||
After completion of the original upstream the elements of the given source will be emitted.
|
||||
|
||||
Both streams will be materialized together.
|
||||
|
||||
@@@ note
|
||||
|
||||
The `concat` operator is for backwards compatibility reasons "detached" and will eagerly
|
||||
demand an element from both upstreams when the stream is materialized and will then have a
|
||||
one element buffer for each of the upstreams, this is most often not what you want, instead
|
||||
use @ref(concatLazy)[concatLazy.md]
|
||||
|
||||
@@@
|
||||
|
||||
## Example
|
||||
Scala
|
||||
: @@snip [FlowConcatSpec.scala](/akka-stream-tests/src/test/scala/akka/stream/scaladsl/FlowConcatSpec.scala) { #concat }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
# concatLazy
|
||||
|
||||
After completion of the original upstream the elements of the given source will be emitted.
|
||||
|
||||
@ref[Fan-in operators](../index.md#fan-in-operators)
|
||||
|
||||
## Signature
|
||||
|
||||
@apidoc[Source.concat](Source) { scala="#concatLazy[U>:Out,Mat2](that:akka.stream.Graph[akka.stream.SourceShape[U],Mat2]):FlowOps.this.Repr[U]" java="#concatLazy(akka.stream.Graph)" }
|
||||
@apidoc[Flow.concat](Flow) { scala="#concatLazy[U>:Out,Mat2](that:akka.stream.Graph[akka.stream.SourceShape[U],Mat2]):FlowOps.this.Repr[U]" java="#concatLazy(akka.stream.Graph)" }
|
||||
|
||||
|
||||
## Description
|
||||
|
||||
After completion of the original upstream the elements of the given source will be emitted.
|
||||
|
||||
Both streams will be materialized together, however, the given stream will be pulled for the first time only after the original upstream was completed. (In contrast, @ref(concat)[concat.md], introduces single-element buffers after both, original and given sources so that the given source is also pulled once immediately.)
|
||||
|
||||
To defer the materialization of the given source (or to completely avoid its materialization if the original upstream fails or cancels), wrap it into @ref(Source.lazySource)[../Source/lazySource.md].
|
||||
|
||||
If materialized values needs to be collected `concatLazyMat` is available.
|
||||
|
||||
## Example
|
||||
Scala
|
||||
: @@snip [FlowConcatSpec.scala](/akka-stream-tests/src/test/scala/akka/stream/scaladsl/FlowConcatSpec.scala) { #concatLazy }
|
||||
|
||||
Java
|
||||
: @@snip [SourceOrFlow.java](/akka-docs/src/test/java/jdocs/stream/operators/SourceOrFlow.java) { #concatLazy }
|
||||
|
||||
## Reactive Streams semantics
|
||||
|
||||
@@@div { .callout }
|
||||
|
||||
**emits** when the current stream has an element available; if the current input completes, it tries the next one
|
||||
|
||||
**backpressures** when downstream backpressures
|
||||
|
||||
**completes** when all upstreams complete
|
||||
|
||||
@@@
|
||||
|
|
@ -14,8 +14,26 @@ Prepends the given source to the flow, consuming it until completion before the
|
|||
|
||||
Prepends the given source to the flow, consuming it until completion before the original source is consumed.
|
||||
|
||||
@@@ note
|
||||
|
||||
The `prepend` operator is for backwards compatibility reasons "detached" and will eagerly
|
||||
demand an element from both upstreams when the stream is materialized and will then have a
|
||||
one element buffer for each of the upstreams, this is most often not what you want, instead
|
||||
use @ref(prependLazy)[prependLazy.md]
|
||||
|
||||
@@@
|
||||
|
||||
If materialized values needs to be collected `prependMat` is available.
|
||||
|
||||
@@@ note
|
||||
|
||||
The `prepend` operator is for backwards compatibility reasons "detached" and will eagerly
|
||||
demand an element from both upstreams when the stream is materialized and will then have a
|
||||
one element buffer for each of the upstreams, this is not always what you want, if not,
|
||||
use @ref(prependLazy)[prependLazy.md]
|
||||
|
||||
@@@
|
||||
|
||||
## Example
|
||||
Scala
|
||||
: @@snip [FlowOrElseSpec.scala](/akka-stream-tests/src/test/scala/akka/stream/scaladsl/FlowPrependSpec.scala) { #prepend }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
# prependLazy
|
||||
|
||||
Prepends the given source to the flow, consuming it until completion before the original source is consumed.
|
||||
|
||||
@ref[Fan-in operators](../index.md#fan-in-operators)
|
||||
|
||||
## Signature
|
||||
|
||||
@apidoc[Source.prepend](Source) { scala="#prepend[U>:Out,Mat2](that:akka.stream.Graph[akka.stream.SourceShape[U],Mat2]):FlowOps.this.Repr[U]" java="#prepend(akka.stream.Graph)" }
|
||||
@apidoc[Flow.prepend](Flow) { scala="#prepend[U>:Out,Mat2](that:akka.stream.Graph[akka.stream.SourceShape[U],Mat2]):FlowOps.this.Repr[U]" java="#prepend(akka.stream.Graph)" }
|
||||
|
||||
|
||||
## Description
|
||||
|
||||
Prepends the given source to the flow, consuming it until completion before the original source is consumed.
|
||||
|
||||
Both streams will be materialized together, however, the original stream will be pulled for the first time only after the prepended upstream was completed. (In contrast, @ref(prepend)[prepend.md], introduces single-element buffers after both, original and given sources so that the original source is also pulled once immediately.)
|
||||
|
||||
If materialized values needs to be collected `prependLazyMat` is available.
|
||||
|
||||
See also @ref[prepend](prepend.md) which is detached.
|
||||
|
||||
## Example
|
||||
Scala
|
||||
: @@snip [FlowPrependSpec.scala](/akka-stream-tests/src/test/scala/akka/stream/scaladsl/FlowPrependSpec.scala) { #prependLazy }
|
||||
|
||||
Java
|
||||
: @@snip [SourceOrFlow.java](/akka-docs/src/test/java/jdocs/stream/operators/SourceOrFlow.java) { #prependLazy }
|
||||
|
||||
## Reactive Streams semantics
|
||||
|
||||
@@@div { .callout }
|
||||
|
||||
**emits** when the given stream has an element available; if the given input completes, it tries the current one
|
||||
|
||||
**backpressures** when downstream backpressures
|
||||
|
||||
**completes** when all upstreams complete
|
||||
|
||||
@@@
|
||||
|
|
@ -262,6 +262,7 @@ the inputs in different ways.
|
|||
|--|--|--|
|
||||
| |<a name="mergesequence"></a>@ref[MergeSequence](MergeSequence.md)|Merge a linear sequence partitioned across multiple sources.|
|
||||
|Source/Flow|<a name="concat"></a>@ref[concat](Source-or-Flow/concat.md)|After completion of the original upstream the elements of the given source will be emitted.|
|
||||
|Source/Flow|<a name="concatlazy"></a>@ref[concatLazy](Source-or-Flow/concatLazy.md)|After completion of the original upstream the elements of the given source will be emitted.|
|
||||
|Source/Flow|<a name="interleave"></a>@ref[interleave](Source-or-Flow/interleave.md)|Emits a specifiable number of elements from the original source, then from the provided source and repeats.|
|
||||
|Source/Flow|<a name="merge"></a>@ref[merge](Source-or-Flow/merge.md)|Merge multiple sources.|
|
||||
|Source/Flow|<a name="mergelatest"></a>@ref[mergeLatest](Source-or-Flow/mergeLatest.md)|Merge multiple sources.|
|
||||
|
|
@ -270,6 +271,7 @@ the inputs in different ways.
|
|||
|Source/Flow|<a name="mergesorted"></a>@ref[mergeSorted](Source-or-Flow/mergeSorted.md)|Merge multiple sources.|
|
||||
|Source/Flow|<a name="orelse"></a>@ref[orElse](Source-or-Flow/orElse.md)|If the primary source completes without emitting any elements, the elements from the secondary source are emitted.|
|
||||
|Source/Flow|<a name="prepend"></a>@ref[prepend](Source-or-Flow/prepend.md)|Prepends the given source to the flow, consuming it until completion before the original source is consumed.|
|
||||
|Source/Flow|<a name="prependlazy"></a>@ref[prependLazy](Source-or-Flow/prependLazy.md)|Prepends the given source to the flow, consuming it until completion before the original source is consumed.|
|
||||
|Source/Flow|<a name="zip"></a>@ref[zip](Source-or-Flow/zip.md)|Combines elements from each of multiple sources into @scala[tuples] @java[*Pair*] and passes the @scala[tuples] @java[pairs] downstream.|
|
||||
|Source/Flow|<a name="zipall"></a>@ref[zipAll](Source-or-Flow/zipAll.md)|Combines elements from two sources into @scala[tuples] @java[*Pair*] handling early completion of either source.|
|
||||
|Source/Flow|<a name="ziplatest"></a>@ref[zipLatest](Source-or-Flow/zipLatest.md)|Combines elements from each of multiple sources into @scala[tuples] @java[*Pair*] and passes the @scala[tuples] @java[pairs] downstream, picking always the latest element of each.|
|
||||
|
|
@ -393,6 +395,7 @@ For more background see the @ref[Error Handling in Streams](../stream-error.md)
|
|||
* [completionStageSource](Source/completionStageSource.md)
|
||||
* [completionTimeout](Source-or-Flow/completionTimeout.md)
|
||||
* [concat](Source-or-Flow/concat.md)
|
||||
* [concatLazy](Source-or-Flow/concatLazy.md)
|
||||
* [conflate](Source-or-Flow/conflate.md)
|
||||
* [conflateWithSeed](Source-or-Flow/conflateWithSeed.md)
|
||||
* [cycle](Source/cycle.md)
|
||||
|
|
@ -504,6 +507,7 @@ For more background see the @ref[Error Handling in Streams](../stream-error.md)
|
|||
* [prefixAndTail](Source-or-Flow/prefixAndTail.md)
|
||||
* [preMaterialize](Sink/preMaterialize.md)
|
||||
* [prepend](Source-or-Flow/prepend.md)
|
||||
* [prependLazy](Source-or-Flow/prependLazy.md)
|
||||
* [queue](Source/queue.md)
|
||||
* [queue](Sink/queue.md)
|
||||
* [range](Source/range.md)
|
||||
|
|
|
|||
|
|
@ -19,7 +19,9 @@ import akka.japi.function.Function2;
|
|||
// #zip-with-index
|
||||
// #or-else
|
||||
// #prepend
|
||||
// #prependLazy
|
||||
// #concat
|
||||
// #concatLazy
|
||||
// #interleave
|
||||
// #merge
|
||||
// #merge-sorted
|
||||
|
|
@ -33,7 +35,9 @@ import java.util.*;
|
|||
// #merge
|
||||
// #interleave
|
||||
// #concat
|
||||
// #concatLazy
|
||||
// #prepend
|
||||
// #prependLazy
|
||||
// #or-else
|
||||
// #zip-with-index
|
||||
// #zip-with
|
||||
|
|
@ -124,6 +128,16 @@ class SourceOrFlow {
|
|||
// #prepend
|
||||
}
|
||||
|
||||
void prependLazyExample() {
|
||||
// #prepend
|
||||
Source<String, NotUsed> ladies = Source.from(Arrays.asList("Emma", "Emily"));
|
||||
Source<String, NotUsed> gentlemen = Source.from(Arrays.asList("Liam", "William"));
|
||||
gentlemen.prependLazy(ladies).runWith(Sink.foreach(System.out::print), system);
|
||||
// this will print "Emma", "Emily", "Liam", "William"
|
||||
|
||||
// #prepend
|
||||
}
|
||||
|
||||
void concatExample() {
|
||||
// #concat
|
||||
Source<Integer, NotUsed> sourceA = Source.from(Arrays.asList(1, 2, 3, 4));
|
||||
|
|
@ -134,6 +148,16 @@ class SourceOrFlow {
|
|||
// #concat
|
||||
}
|
||||
|
||||
void concatLazyExample() {
|
||||
// #concat
|
||||
Source<Integer, NotUsed> sourceA = Source.from(Arrays.asList(1, 2, 3, 4));
|
||||
Source<Integer, NotUsed> sourceB = Source.from(Arrays.asList(10, 20, 30, 40));
|
||||
sourceA.concatLazy(sourceB).runWith(Sink.foreach(System.out::print), system);
|
||||
// prints 1, 2, 3, 4, 10, 20, 30, 40
|
||||
|
||||
// #concat
|
||||
}
|
||||
|
||||
void interleaveExample() {
|
||||
// #interleave
|
||||
Source<Integer, NotUsed> sourceA = Source.from(Arrays.asList(1, 2, 3, 4));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue