Bha*_*mar -2 scala scala-collections
我有一个场景,我以对象流的形式获得数据库数据.在将其转换为Object序列时,需要时间.我正在寻找替代方案,花费更少的时间.
快速回答:Scala流已经是Scala序列,根本不需要转换.以下进一步说明......
甲Scala的序列(scala.collection.Seq)是简单地存储在一个特定的顺序元件(顺序是任意的,但一旦定义的元素顺序不改变)的序列的任何集合.
一个斯卡拉名单(scala.collection.immutable.List)是的子类Seq,也是一个默认的实现scala.collection.Seq.也就是说,Seq(1, 2, 3)实现为List(1, 2, 3).Lists是严格的,因此列表上的任何操作都可以在执行另一个操作之前一个接一个地处理所有元素.
例如,请考虑Scala REPL中的此示例:
$ scala
Welcome to Scala 2.12.5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_171).
Type in expressions for evaluation. Or try :help.
scala> val xs = List(1, 2, 3)
xs: List[Int] = List(1, 2, 3)
scala> xs.map {x =>
| val newX = 2 * x
| println(s"Mapping value $x to $newX...")
| newX
| }.foreach {x =>
| println(s"Printing value $x")
| }
Mapping value 1 to 2...
Mapping value 2 to 4...
Mapping value 3 to 6...
Printing value 2
Printing value 4
Printing value 6
Run Code Online (Sandbox Code Playgroud)
请注意每个值如何映射,在打印出新列表的任何值之前创建新列表(List(2, 4, 6))?
甲Scala的流(scala.collection.immutable.Stream)也是的一个子类Seq,但它是懒惰(或不严格),这意味着在需要时从该流的下一个值只取.它通常被称为惰性列表.
为了说明a Stream和a 之间的区别List,让我们重做那个例子:
scala> val xs = Stream(1, 2, 3)
xs: scala.collection.immutable.Stream[Int] = Stream(1, ?)
scala> xs.map {x =>
| val newX = 2 * x
| println(s"Mapping value $x to $newX...")
| newX
| }.foreach {x =>
| println(s"Printing value $x")
| }
Mapping value 1 to 2...
Printing value 2
Mapping value 2 to 4...
Printing value 4
Mapping value 3 to 6...
Printing value 6
Run Code Online (Sandbox Code Playgroud)
请注意,对于a Stream,我们只在完成前一个元素的所有map操作后才处理下一个操作?该操作仍返回一个新的stream(),但仅在需要时才会获取值.MapStream(2, 4, 6)
在任何特定情况下Stream表现是否优于某项表现List将取决于您正在尝试做什么.如果性能是您的主要目标,我建议您对代码进行基准测试(使用ScalaMeter等工具)来确定哪种类型效果最佳.
顺便说一句,因为这两个Stream和List是的子类Seq,通常的做法是写要求的序列利用代码Seq.这样,您可以提供一个List 或一个Stream 或任何其他Seq子类,而无需更改代码,也无需将列表,流等转换为序列.例如:
def doSomethingWithSeq[T](seq: Seq[T]) = {
//
}
// This works!
val list = List(1, 2, 3)
doSomethingWithSeq(list)
// This works too!
val stream = Stream(4, 5, 6)
doSomethingWithSeq(stream)
Run Code Online (Sandbox Code Playgroud)
更新
的性能List对比Stream的groupBy操作将是非常相似的.根据它的使用方式,a Stream可能需要的内存少于a List,但可能需要一些额外的CPU时间.如果收集性能肯定是问题,那么对两种类型的收集(见上文)进行基准测试并精确测量以确定两者之间的权衡.我无法为你做出决心.您引用的缓慢可能是数据库和应用程序之间的数据传输,而与集合类型无关.
有关Scala集合性能的一般信息,请参阅集合:性能特征.
更新2
另请注意,任何类型的Scala序列通常一次由一个线程按顺序处理(因此名称).既不List也不Stream适合并行处理其元素.如果需要并行处理集合,则需要并行集合类型(其中一个集合scala.collection.parallel).A scala.collection.parallel.ParSeq应该groupBy比a List或a 更快地处理Stream,但前提是你有多个核心/超线程可用.但是,ParSeq操作不保证保留分组的元素的顺序.