Scala学习笔记:函数编程&集合

Functional Programming

lambda

匿名函数(至少python是叫lambda)算是FO的基本功能了。scala定义一个匿名函数按照如下格式:

object Main {

  def main(args: Array[String]): Unit = {
    val say = (sth: String) => {println("say: %s".format(sth))}
    say("hello")
    say("world")
  }
}

// output:
// say: hello
// say: world

Using pattern matching

scala中,pattern matching的逻辑语句使用频率很高,配合case class可以代替if用在一些条件判断的情况

object Main {

  def main(args: Array[String]): Unit = {
    def fibonacci(in: Any): Int = {
      in match {
        case 0 => 0
        case 1 => 1
        case n: Int => fibonacci(n - 1) + fibonacci(n -2)
        case _ => 0
      }
    }

    println(fibonacci("ABC"))
    println(fibonacci(3))
  }
}

// output:
// 0
// 2

Case Class

Case class是特殊的class:

  1. Case class的创建不需要new操作符
  2. Case class可作为case matching参数
object Main {

  def main(args: Array[String]): Unit = {
    trait Exp {}

    case class Value(value: Int) extends Exp {}
    case class Sum(l: Value, r: Value) extends Exp {}
    case class Sub(l: Value, r: Value) extends Exp {}

    def compute(exp: Exp): Int = {
      exp match {
        case Value(v) => v
        case Sum(l, r) => compute(l) + compute(r)
        case Sub(l, r) => compute(l) - compute(r)
        case _ => 0
      }
    }

    // 1 + 2
    val case1 = Sum(Value(1), Value(2))
    // 10 - 5
    val case2 = Sub(Value(10), Value(5))

    println(compute(case1))
    println(compute(case2))
  }
}

// output
// 3
// 5

option and check null pointer

scala加入了option的概念。option用来封装一个值,并将java的null判断语句封装在其中。个人感觉,和java相比,option的引入带来的好处是将null的判断由optional级别提升到了mandatory:java中可能由于代码的不规范,有可能漏掉是否为null的判断,但是scala加了option,在写代码的时候,至少起到reminder的作用。

object Main {

  def main(args: Array[String]): Unit = {

    def printEnv = (name: String) => {

      val getEnv = (name: String) => {
        if (sys.env.contains(name)) {
          Some(sys.env(name))
        } else {
          None
        }
      }

      def handleEnv(name: String, opt: Option[String]): Unit = {
        opt match {
          case Some(h) => {
            println("%s=%s".format(name, h))            // get value through case matching
            println("%s get %s".format(name, opt.get))  // get value through get()
          }
          case None => {
            println("%s is undefined".format(name))     // get none value through case matching
          }
        }
        println("%s getOrElse %s".format(name, opt.getOrElse("none_env")))  //get value through getOrElse
      }

      handleEnv(name, getEnv(name))
    }

    printEnv("HOME")
    println()
    printEnv("JAVA_HOME")
  }
}

// output:
// HOME is undefined
// HOME getOrElse none_env

// JAVA_HOME=C:\Program Files\Java\jdk1.8.0_101
// JAVA_HOME get C:\Program Files\Java\jdk1.8.0_101
// JAVA_HOME getOrElse C:\Program Files\Java\jdk1.8.0_101

在通过get()拿值的时候,如果为空,则会抛出NoSuchElementException.

Lazy initialization

在属性前添加lazy可以让该属性在第一次使用时才被初始化。
默认情况下,是在创建对象时初始化的:

object Main {

  def main(args: Array[String]): Unit = {
    class Person {
      val name = {          // without lazy
        println("init name...")
        "Lilei"
      }
    }

    val person = new Person()
    println("create a person")
    println("name: %s".format(person.name))
  }
}

// output:
// init name...
// create a person
// name: Lilei

添加lazy后则是使用时才初始化:

object Main {

  def main(args: Array[String]): Unit = {
    class Person {
      lazy val name = {         // without lazy
        println("init name...")
        "Lilei"
      }
    }

    val person = new Person()
    println("create a person")
    println("name: %s".format(person.name))
  }
}

// output:
// create a person
// init name...
// name: Lilei

For loop and yield:

for循环和java基本一致,多了一些额外的增强。

Simple For

  1. 简单遍历index可以通过range的方式:tountilto包含最后一个index,until不包括
  2. 也可以通过range generator实现:
  • 一个for循环申明也可以实现多个嵌套的循环
object Main {

  def main(args: Array[String]):Unit = {
    for (i <- 1 to 3; j <- 1 until 3) println("%d - %d".format(i, j))       // range & nested for

    println()
    val numbers = List(1,2,3,4,5,6)
    for (i <- numbers) println("%d".format(i))      // range generator
  }
}

// output:
// 1 - 1
// 1 - 2
// 2 - 1
// 2 - 2
// 3 - 1
// 3 - 2

// 1
// 2
// 3
// 4
// 5
// 6

filter & yield

另外还多了filteryield的概念。
filter即在for循环申明时可以多加些判断条件进行过滤
yield可以从for循环返回一个List

object Main {

  def main(args: Array[String]): Unit = {
    case class Person(name: String, age: Int)   // case class has no need to new it

    val persons: List[Person] = List(
      Person("Lilei",     14),
      Person("HanMeimei", 15),
      Person("Lily",      16),
      Person("Lucy",      17)
    )

    val adults = for (p<-persons  if p.name startsWith "L"; if p.age >= 16)   // filters
      yield p

    for (a <- adults) {
      println("%s is an adult starts with L".format(a.name))
    }
  }
}

// output:
// Lily is an adult starts with L
// Lucy is an adult starts with L

Collection

scala中collecion分为strictlazy两种,lazy的collection中的元素只会在使用的时候被分配内存,比如range
另外collection还可以被申明为mutableimmutable两种(immutable collection也能包含mutable元素),分别在scala.collection, scala.collection.immutable, scala.collection.mutable包中。

他们各自适应于不同的场景,immutable更适合与多线程场景。建议的做法是先申明为immutable的,当出现需要时,再改为mutable的。

Collection API

filterMapReduce方法可以参考:https://www.tutorialspoint.com/scala/scala_collections.htm

Collection Operatin

默认情况下申明的collection都是immutable的,mutable collection需要导入包scala.collection.mutable

// create immutable collection
val list = List("a", "b")
val map = Map("a" -> 1, "b" -> 2)
val set = Set(1, 2)

// create mutable collection
import scala.collection.mutable._

val listBuffer = ListBuffer("a", "b")
val hashMap = HashMap("a" -> 1, "b" -> 2)
val hashSet = HashSet(1, 2)

immutable不支持append操作,对他们的操作会返回一个新的collection:

// add opertions: the original collections change nothing
val newList = list + "c"                // newList: ("a", "b", "c")
val newMap = map + ("c" -> 3)
val newSet = set + 3

// mutable
listBuffer += "c"
hashMap += ("c" -> 3)
hashSet += 3
  • +-immutablemutable都支持,自身不变,返回新的结果集合
  • +=, -=:仅mutable支持
  • 修改操作可通过+重复key实现
  • ::::连接两个集合
val col = colA ::: colB
  • Tail Recursion:
list match {
  case List() => init
  case head :: tail => ...      // head is the first elem, tail is the rest
}

Parallel Collection

通过.par方法可以返回当前集合的一个并行实现。

  • 一般情况下,返回的都是一个copy,这会花费线性时间,并且新生成的集合和原集合的数据是不共享的。
  • 但是对于ParArraymutable.ParHashMap(HashMap.par的返回类型),是会共享原数据的,所以花费的时间是固定的。
object Parallel {

  def main(args: Array[String]):Unit = {
    val list = List(1, 2, 3, 4)
    val newList = list.par.map((e) => {e + 1})

    println(newList)
  }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容