爲加強對函數式編程的理解,同時鞏固Scala語法,這裏分析一個實例:對某個目錄下所有文件中的單詞進行詞頻統計。
【源碼】
import java.io.File
import scala.io.Source
import collection.mutable.Map
object WordCount{
def main(args: Array[String]){
val dirfile = new File("testfiles")
val files = dirfile.listFiles
val results = Map.empty[String,Int]
for(file <- files){
val data = Source.fromFile(file)
val strs = data.getLines.flatMap{s => s.split(" ")}
strs foreach{
word =>
if(results.contains(word)) results(word)+=1 else results(word)=1
}
}
results foreach{case (k,v) => println(s"$k:$v")}
}
}
【分析】
- 行1~3:導入需要的類。
- 行6:
val dirfile = new File("testfiles")
建立一個File對象,這裏假設當前文件夾下有個testfiles文件夾,且裏面包含若干文本文件。
-
行7:
val files = dirfile.listFiles
調用File對象的listFiles方法,得到其下所有文件對象構成的數組,file的類型爲Array[java.io.File]。
-
行8:
val results = Map.empty[String,Int]
建立一個可變的空的映射(Map)對象results,保存統計結果。映射中的條目都是一個(key,value)鍵值對,其中,key是單詞,value是單詞出現的次數。(映射是指通過對容器中的元素進行某些運算來生成一個新的容器。兩個典型的映射操作是map方法和flatMap方法。)
-
行9:
for(file <- files){
通過for循環對文件對象進行循環,分別處理各個文件。
-
行10:
val data = Source.fromFile(file)
從File對象建立Source對象,方便文件的讀取。
-
行11:
val strs = data.getLines.flatMap{s => s.split(" ")}
getLines方法返回文件各行構成的迭代器對象,類型爲Iterator[String],flatMap進一步將每行字符串拆分成單詞,再返回所有這些單詞構成的新字符串迭代器。
-
行12~15:
strs foreach{ word => if(results.contains(word)) results(word)+=1 else results(word)=1 }
對上述的字符串迭代器進行遍歷,在匿名函數中,對於當前遍歷到的某個單詞,如果這個單詞以前已經統計過,就把映射results中以該單詞爲key的映射條目的value增加1。如果以前沒有被統計過,則爲這個單詞創建一個映射條目,只需要直接對應的key進行賦值,就實現了添加新的條目。
-
行17:
results foreach{case (k,v) => println(s"$k:$v")}
對Map對象results進行遍歷,輸出統計結果。