在Akka Streams中实施chopBy

时间:2016-09-01 14:25:58

标签: scala akka akka-stream scala-streams

回答this question,Odomontois展示了如何实现一个懒惰的group-by运算符,它可以通过键对预先排序的流进行分组,而无需将整个内容存储在内存中。有没有办法用Akka的流(即Source对象)做这样的事情?或者,有没有办法从Akka Source中提取常规的Stream对象,这样我就可以使用Odomontois的chopBy?

这是完全失败的尝试做到这一点并不起作用:

  implicit class SourceChopOps[T, NU](s: Source[T, NU]) {
    def chopBy[U](f: T => U) = {
      s.prefixAndTail(1)
        .map(pt => (pt._1.head, pt._2))
        .map {
          case (prefix, tail) =>
            // what to do with pulled off head???
            tail.takeWhile(e => f(e) == f(prefix)) ++ tail.dropWhile(e => f(e) == f(prefix)).chopBy(f) // fails here
        }
      }
    }
  }

1 个答案:

答案 0 :(得分:0)

Akka Streams中的

groupBy将保留您在内存中分组的密钥,但是流区域总是“懒惰”,因为它们具有反压,因此它将在有限的内存中运行。如果下游不接受新元素,则不会在上游生成新元素。

例如:

case class Record(id: Int)
Source.fromIterator(() => 
    Iterator
      .fill(1000)(Iterator(1,2).map { n => println("creating"); Record(n) })
      .flatten)
  .groupBy(maxSubstreams = 2, _.id)
  .map { r => println("Consuming"); r }
  .fold(0)((acc, _) => acc + 1)
  .mergeSubstreams
  .runForeach(println)

将向您展示如何生成Record个实例的速度,因为它们可以在两个子流中的每一个中消耗,而不是预先全部消耗。