Jes*_*har 50 scala stream scala-collections
在Scala中有一个Stream类,它非常像迭代器.主题Scala中Iterator和Stream之间的区别?提供了两者之间相同点和不同点的一些见解.
看看如何使用流非常简单,但我没有很多常见的用例,我会使用流而不是其他工件.
我现在的想法:
所以我错过了任何重大用途吗?或者它是大多数开发人员的偏好?
谢谢
Dan*_*ral 40
a Stream和an 之间的主要区别在于Iterator后者是可变的和"一次性",可以这么说,而前者则不是.Iterator具有更好的内存占用Stream,但它是可变的这一事实可能不方便.
拿这个经典的素数发生器,例如:
def primeStream(s: Stream[Int]): Stream[Int] =
Stream.cons(s.head, primeStream(s.tail filter { _ % s.head != 0 }))
val primes = primeStream(Stream.from(2))
Run Code Online (Sandbox Code Playgroud)
它也可以很容易地编写Iterator,但是到目前为止Iterator还不会保留计算的素数.
因此,a的一个重要方面Stream是,您可以将其传递给其他函数,而不必先将其复制,或者必须一次又一次地生成它.
至于昂贵的计算/无限列表,这些事情也可以完成Iterator.无限列表实际上非常有用 - 你只是不知道它,因为你没有它,所以你已经看到了比处理强制有限大小更严格的算法.
Rex*_*err 18
除了Daniel的回答之外,请记住,这Stream对于短路评估很有用.例如,假设我有一大堆可以接收String和返回的函数,Option[String]我想继续执行它们直到其中一个工作:
val stringOps = List(
(s:String) => if (s.length>10) Some(s.length.toString) else None ,
(s:String) => if (s.length==0) Some("empty") else None ,
(s:String) => if (s.indexOf(" ")>=0) Some(s.trim) else None
);
Run Code Online (Sandbox Code Playgroud)
好吧,我当然不想执行整个列表,并且没有任何方便的方法List,说"将这些作为函数处理并执行它们,直到其中一个返回除None"之外的其他内容.该怎么办?也许这个:
def transform(input: String, ops: List[String=>Option[String]]) = {
ops.toStream.map( _(input) ).find(_ isDefined).getOrElse(None)
}
Run Code Online (Sandbox Code Playgroud)
这需要一个列表并将其视为一个Stream(实际上并没有评估任何东西),然后定义一个新的Stream,它是应用函数的结果(但是还没有评估任何东西),然后搜索第一个定义 - 在这里,神奇地,它回顾并意识到它必须应用地图,并从原始列表中获取正确的数据 - 然后将其从打开Option[Option[String]]到Option[String]使用getOrElse.
这是一个例子:
scala> transform("This is a really long string",stringOps)
res0: Option[String] = Some(28)
scala> transform("",stringOps)
res1: Option[String] = Some(empty)
scala> transform(" hi ",stringOps)
res2: Option[String] = Some(hi)
scala> transform("no-match",stringOps)
res3: Option[String] = None
Run Code Online (Sandbox Code Playgroud)
但它有效吗?如果我们println在我们的函数中加入一个函数,那么我们可以判断它们是否被调用了
val stringOps = List(
(s:String) => {println("1"); if (s.length>10) Some(s.length.toString) else None },
(s:String) => {println("2"); if (s.length==0) Some("empty") else None },
(s:String) => {println("3"); if (s.indexOf(" ")>=0) Some(s.trim) else None }
);
// (transform is the same)
scala> transform("This is a really long string",stringOps)
1
res0: Option[String] = Some(28)
scala> transform("no-match",stringOps)
1
2
3
res1: Option[String] = None
Run Code Online (Sandbox Code Playgroud)
(这与Scala 2.8有关;遗憾的是,2.7的实现有时会超过一个.并且请注意,当你的失败累积时,你会积累一长串列表None,但可能这与你在这里的真实计算相比是便宜的.)
我可以想象,如果您实时轮询某些设备,Stream会更方便.
想象一下GPS追踪器,如果你问它,它会返回实际位置.您无法预先计算5分钟内的位置.您可能只使用它几分钟来实现OpenStreetMap中的路径,或者您可以将它用于沙漠或雨林中六个月的探险.
或者是数字温度计或其他类型的传感器,只要硬件处于活动状态并且打开,它们就会重复返回新数据 - 日志文件过滤器可能是另一个例子.
| 归档时间: |
|
| 查看次数: |
15166 次 |
| 最近记录: |