scala - Scala Stream vs Scala List vs Scala Sequence有什么区别
问题描述
我有一个场景,我以对象流的形式获取数据库数据。在将其转换为一系列对象时,它需要时间。我正在寻找需要更少时间的替代方案。
解决方案
快速回答:Scala 流已经是Scala 序列,根本不需要转换。下面进一步解释...
Scala 序列( ) 只是任何scala.collection.Seq
以特定顺序存储元素序列的集合(顺序是任意的,但元素顺序一旦定义就不会改变)。
Scala list ( scala.collection.immutable.List
) 是 a 的子类,也是aSeq
的默认实现scala.collection.Seq
。也就是说,Seq(1, 2, 3)
实现为List(1, 2, 3)
. List
s 是严格的,因此列表上的任何操作都会处理所有元素,一个接一个,然后才能执行另一个操作。
例如,考虑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
请注意在打印出新列表的任何值之前如何映射每个值,创建一个新列表 ( List(2, 4, 6)
) ?
Scala 流( scala.collection.immutable.Stream
) 也是 的子类,Seq
但它是惰性的(或非严格的),这意味着仅在需要时才获取流中的下一个值。它通常被称为惰性列表。
Stream
为了说明 a和 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
请注意,对于 a Stream
,我们如何只在前一个元素的所有map
操作都完成后才处理下一个操作?该操作仍会返回一个新流 ( ),但仅在需要时才获取值。Map
Stream(2, 4, 6)
在任何特定情况下,a是否Stream
比 a 表现更好List
将取决于您要做什么。如果性能是您的主要目标,我建议您对代码进行基准测试(使用诸如ScalaMeter 之类的工具)以确定哪种类型最有效。
顺便说一句,因为Stream
和List
都是 的子类Seq
,所以通常的做法是编写需要使用序列的代码Seq
。这样,您可以提供 aList
或aStream
或任何其他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)
更新
一个操作的List
vs.性能将非常相似。根据它的使用方式, a可能需要比 a 更少的内存,但可能需要一些额外的 CPU 时间。如果收集性能肯定是问题,请对两种类型的收集进行基准测试(见上文)并精确测量以确定两者之间的权衡。我不能为你做出那个决定。您提到的缓慢可能归结为数据库和应用程序之间的数据传输,与集合类型无关。Stream
groupBy
Stream
List
有关Scala集合性能的一般信息,请参阅集合:性能特征。
更新 2
另请注意,任何类型的Scala序列通常会一次由一个线程按顺序处理(因此得名)。既不List
也不Stream
适合并行处理其元素。如果需要并行处理集合,则需要并行集合类型( 中的集合之一scala.collection.parallel
)。Ascala.collection.parallel.ParSeq
应该groupBy
比 aList
或 a处理得更快Stream
,但前提是您有多个可用的内核/超线程。但是,ParSeq
操作不能保证保留分组元素的顺序。
推荐阅读
- javascript - 针对特定窗口大小重新加载网站一次
- python - 解密要更改的 json 字典 Python
- css - 如何在 ASP.Net Core 5.0 项目中添加我自己的 css
- r - R分组条形图中具有不同字体大小的x轴标签的两行
- odoo - 查看联系人的会议
- c++ - 初始化 SSL 以使用 TLSv1.2 而不是 TLSv1.0 与 Pocco C++ 库
- javascript - 我们可以在 sinun.stub 中替换同一资源的多个方法吗
- bitwise-operators - 小于等于limit的最大偶数
- reactjs - 即使在 useEffect 钩子中使用异步调用,对象作为 React 子项也无效(找到:[object Promise])
- null - 联动节区有空地址