[英]What are some good use cases of lazy evaluation in Scala?
在處理大型館藏時,我們通常會聽到“惰性評估”一詞。 我想更好地說明嚴格評估和惰性評估之間的區別,因此我嘗試了以下示例-從列表中獲取前兩個偶數:
scala> var l = List(1, 47, 38, 53, 51, 67, 39, 46, 93, 54, 45, 33, 87)
l: List[Int] = List(1, 47, 38, 53, 51, 67, 39, 46, 93, 54, 45, 33, 87)
scala> l.filter(_ % 2 == 0).take(2)
res0: List[Int] = List(38, 46)
scala> l.toStream.filter(_ % 2 == 0).take(2)
res1: scala.collection.immutable.Stream[Int] = Stream(38, ?)
我注意到當我使用toStream
,我得到了Stream(38, ?)
toStream
Stream(38, ?)
。 什么是“?” 是這里嗎 這與懶惰評估有關嗎?
另外,什么是延遲評估的好例子,什么時候應該使用它,為什么?
使用惰性集合的一個好處是“保存”內存,例如在映射到大型數據結構時。 考慮一下:
val r =(1 to 10000)
.map(_ => Seq.fill(10000)(scala.util.Random.nextDouble))
.map(_.sum)
.sum
並使用惰性評估:
val r =(1 to 10000).toStream
.map(_ => Seq.fill(10000)(scala.util.Random.nextDouble))
.map(_.sum)
.sum
第一條語句將生成大小為10000的10000 Seq
並將其保留在內存中,而在第二種情況下,一次只需要在內存中存在一個Seq
,因此它的速度要快得多...
另一個用例是實際只需要一部分數據時。 我經常將惰性集合與take
, takeWhile
等一起使用
讓我們來看一個現實生活中的場景-您沒有一個列表,而是擁有一個大型日志文件,您希望提取其中包含“成功”的前10行。
直接的解決方案是逐行讀取文件,一旦包含“成功”的行,則將其打印並繼續下一行。
但是因為我們喜歡函數式編程,所以我們不想使用傳統的循環。 相反,我們希望通過組合功能來實現我們的目標。
第一次嘗試:
Source.fromFile("log_file").getLines.toList.filter(_.contains("Success")).take(10)
讓我們嘗試了解這里實際發生的情況:
我們閱讀了整個文件
過濾相關行
拿了前10個元素
如果嘗試打印Source.fromFile("log_file").getLines.toList
,則將獲取整個文件,這顯然是浪費,因為並非所有行都與我們相關。
為什么我們得到所有行,然后才執行過濾? 這是因為List是嚴格的數據結構,因此當我們調用toList
,它將立即求值,並且僅在擁有全部數據之后才應用過濾。
幸運的是,Scala提供了惰性數據結構, 流是其中之一:
Source.fromFile("log_file").getLines.toStream.filter(_.contains("Success")).take(10)
為了演示差異,讓我們嘗試:
Source.fromFile("log_file").getLines.toStream
現在我們得到類似:
Scala.collection.immutable.Stream[Int] = Stream(That's the first line, ?)
toStream
僅計算一個元素 -文件的第一行。 下一個元素由“?”表示,表示流尚未評估下一個元素,這是因為toStream
是lazy function ,並且僅在使用時評估下一項。
現在,在應用過濾器功能之后,它將開始讀取下一行,直到獲得包含“成功”的第一行:
> var res = Source.fromFile("log_file").getLines.toStream.filter(_.contains("Success"))
Scala.collection.immutable.Stream[Int] = Stream(First line contains Success!, ?)
現在,我們將take
功能。 仍然沒有執行任何操作,但是它知道應該選擇10行,因此在我們使用結果之前它不會評估:
res foreach println
最后,我們現在打印res
,正如我們期望的那樣,我們將獲得一個包含前10行的Stream。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.