假設Student類如下:
class Student { private int no; private String name; public int getNo() { return no; } public String getName() { return name; } }
java中獲取Student對象鏈表的方法為:
List<Student> getStudents(){ ... return studentList; }
在scala中獲取no = 1 的student的name:
getStudents().find(_.getNo == 1).map(_.getName)
復雜例子:
函數式編程鼓勵使用流水線轉換將一個不可變的集合塑造為想要的結果。這常常會有非常簡明的方案,但也容易迷糊讀者——很難領悟作者的意圖,或跟蹤所有隱含的中間結果。例如,我們想要從一組語言中匯集不同的程序語言的投票,按照得票的順序顯示(語言,票數):
val votes = Seq(("scala", 1), ("java", 4), ("scala", 10), ("scala", 1), ("python", 10)) val orderedVotes = votes .groupBy(_._1) .map { case (which, counts) => (which, counts.foldLeft(0)(_ + _._2)) }.toSeq .sortBy(_._2) .reverse
上面的代碼簡潔並且正確,但幾乎每個讀者都不能理解作者的原本意圖。一個策略是聲明中間結果和參數:
val votesByLang = votes groupBy { case (lang, _) => lang } val sumByLang = votesByLang map { case (lang, counts) => val countsOnly = counts map { case (_, count) => count } (lang, countsOnly.sum) } val orderedVotes = sumByLang.toSeq .sortBy { case (_, count) => count } .reverse
代碼也同樣簡潔,但更清晰的表達了轉換的發生(通過命名中間值),和正在操作的數據的結構(通過命名參數)。如果你擔心這種風格污染了命名空間,用大括號{}來將表達式分組:
val orderedVotes = { val votesByLang = ... ... }