这半年多来,对Scala/Spark接触很多,而越学习,越感到之前的无知,所谓“学然后知不足”。函数式编程的思维方式和之前Java的或者说面向对象的思维方式有很大不同,而思维惯性又难克服,必须有意识地使用这样风格去思考。

举个简单的例子: 查找某个文件夹下所有文件内容,将所有”db.xxx”的内容中的xxx找出来。

我熟悉Java,之前使用Java实现过,不外是递归遍历根文件夹,对找到的文件逐行扫描,碰到就找出来。用Scala实现的时候遇到一些困难,主要是思考方式的挑战。最终解决的时候,算是彻底明白了Map和Reduce,并震惊于这种解决方式的简练和优雅!

object Sample extends App{
  val dir = new File("src/main/")

  println (s"Find all matches from the src folder: ${dir.getAbsolutePath}")

  getFiles(dir)             //fild all files of this folder

  .flatMap(findTableNames)  //onefile -> List  so we need to use flatMap instead of map

  .distinct
  .sorted
  .foreach(println)

  /**
   * get all files
   */
  def getFiles(file: File): Array[File] = {
    val files = file.listFiles()
      .filter(! _.isDirectory)
      .filter(_.getName.endsWith(".scala"))

    files ++ file.listFiles().filter(_.isDirectory).flatMap(getFiles)
  }

  /**
   * get the matches from one file
   */
  def findTableNames(file: File): List[String] = {
    val source = Source.fromFile(file, "UTF-8")
    val lines = source.mkString
    source.close

    //match "db.xxx" until a space or , or newline 

    val pattern = new Regex("(?<=db\\.)[a-zA-Z0-9_]+(?=[,\\s\\n])")    
    pattern.findAllIn(lines).toList.distinct
  }
}