[英]Akka stream sort by id in java
我需要在java中按id对我的akka流列表进行排序我在akka源中有对象列表:
SystemCodeTracking{id=9, EntityName='table3'}
SystemCodeTracking{id=2, EntityName='table2'}
SystemCodeTracking{id=10, EntityName='table1'}
我需要将其排序为:
SystemCodeTracking{id=2, EntityName='table2'}
SystemCodeTracking{id=9, EntityName='table3'}
SystemCodeTracking{id=10, EntityName='table1'}
代码应如下所示:
Source<SystemCodeTracking, SourceQueueWithComplete<SystemCodeTracking>> loggedSource = source.map(single -> sortingFunction(single));
我的问题是如何做sortingFunction
?
排序基本上会破坏流的性质,因为您需要消耗整个流 - 即将其装入内存 - 以应用排序功能。 无论如何,可以通过将整个源耗尽到Sink.seq
,然后对结果进行排序。
source.runWith(Sink.seq, materializer)
然后在完成阶段结果调用
sortingFunction(result)
如果您想对源代码的块进行排序,而不是对整个内容进行排序,则可以执行以下操作
source.grouped(10).map(batch -> sortingFunction(batch))
如果找不到该序列的最小元素(将在结果排序流中首先发出),则无法对序列进行排序(无论是 Akka Stream 还是其他任何东西)。 如果流是无限的,通常就是这种情况。
在某些情况下,您甚至可以对无限流进行排序,即使在低内存限制内 - 例如,如果您可以通过仅查看 N 个最后一个元素来确定下一个最小元素。 或者您可以利用特定于案例的知识,当满足some_condition时,您可以确保some_class元素永远不会出现在您的流中。
否则,您唯一的选择就是将排序问题升级一级:您真的需要流中的强顺序吗? 也许仅仅对流进行分区就足够了——即将它分成具有相同键的元素的子流?
我想 Akka Streams 没有Flow.sort
的原因是 Akka Streams 都是关于资源消耗的有界性,并且Flow.sort
进行排序需要 O(n) 的内存。
根据定义,流是无界的 => 提供完美的排序需要在发出第一个数据之前观察所有数据。
然而,在很多情况下,可以假设流只是部分未排序,也就是说,由于并发处理,数据会稍微混淆,尽管每个元素最终不会超过 1000 个位置它的真实位置。
在这种情况下,您可以使用带有缓冲区的排序方法,如下所示:
* partial sort of a stream: wait for <bufferSize> to be buffered, the start flushing them out in order
* */
def sort[T, S](bufferSize: Int, order: T => S)(implicit ordering: Ordering[S]): () => T => Iterable[T] = () => {
var buffer = List.empty[T]
t: T => {
buffer = (buffer :+ t).sortBy(order)
if (buffer.size < bufferSize) Iterable.empty[T]
else {
val r = buffer.head
buffer = buffer.tail
List(r)
}
}
}
它可以简单地用作statefulMapConcat
一部分,如下所示:
someSource
// sort the stream by timestpam, using a buffer of 1000,
.statefulMapConcat(sort(1000, _.timestamp))
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.