Scala学习笔记(二) 官方教程的学习2

以下内容基于对官方教程 SCALA BOOK 英文版的学习,文字和代码内容绝大多数来源于官方教程,顺序有所改变。与Scala学习笔记(一)重复的部分不再记载。

目录

基础

  特质App

  BigInt和BigDecimal

  字符串连接方式和字符串插值(string interpolation)

  命令行IO

流程控制

  if/else

  for循环

  match模式匹配

  异常处理

案例对象(case objects)

动态混入特质(Mixing traits in on the fly)

抽象类

Scala集合

  ArrayBuffer

  List

  Vector

  Map

  Set

  集合序列的常用方法


​​​​​​​

基础


  特质App


    一般的程序入口需要自己定义main方法,继承特质App后不用写main方法,类体代码会自动执行。
    原因是特质App有main方法,并会把类体代码一一执行。App继承了DelayedInit,会延迟初始化。
  

    object HelloYou extends App {
      if (args.size == 0)
          println("Hello, you")
      else
          println("Hello, " + args(0))
    }


  BigInt和BigDecimal


    对于大数,Scala 还包括类型BigInt和BigDecimal
    两种类型都支持直接使用算术运算符

  字符串连接方式和字符串插值(string interpolation)

    val name = firstName + " " + mi + " " + lastName
    val name = s"$firstName ${mi} $lastName"
    println(s"Name: ${firstName} ${mi} ${lastName}")
    println(s"1+1 = ${1+1}")

    // 双$转义输出一个$
    println(s"New offers starting at $$14.99")

    // 加f可以到达类似printf格式化输出的目的
    val height = 1.9d
    val name = "James"
    println(f"$name%s is $height%2.2f meters tall")  // James is 1.90 meters tall

    // 加raw不会进行转义
    println(raw"a\nb")  // a\nb

    // 双引号需要转义时可以包含在三个双引号之间
    val person = """{"name":"James"}"""  // 输出内容:{"name":"James"}

    // 多行字符串包含在三个双引号之间
    // 从第二行开始缩进空格也会包含在字符串内容中
    val speech = """Four score and
               seven years ago
               our fathers ..."""
    // 从第二行开始文字前放|,最后加stripMargin会保证左对齐
    val speech = """Four score and
               |seven years ago
               |our fathers ...""".stripMargin

    // 可以自定义字符串插值,例如
    implicit class JsonHelper(val sc: StringContext) extends AnyVal {
      def json(args: Any*): JSONObject = {
        val strings = sc.parts.iterator
        val expressions = args.iterator
        var buf = new StringBuilder(strings.next())
        while(strings.hasNext) {
          buf.append(expressions.next())
          buf.append(strings.next())
        }
        parseJson(buf)
      }
    }
    /* 当使用 json"{ name: $name, id: $id }"时,编译器会重写为
       new StringContext("{ name: ", ", id: ", " }").json(name, id)
       然后会利用隐式类再次重写为
       new JsonHelper(new StringContext("{ name: ", ", id: ", " }")).json(name, id)
    */

  命令行IO

    println("Hello, world")
    print("Hello without newline")
    System.err.println("yikes, an error happened")
    val firstName = readLine()

流程控制


  if/else


    if/else结构和java类似
    与java不同的是可以当作三目运算符给变量赋值

    if (a == b) doSomething()
    if (test1) {
        doX()
    } else if (test2) {
        doY()
    } else {
        doZ()
    }
    val minValue = if (a < b) a else b

  for循环

    val nums = Seq(1,2,3)
    for (n <- nums) println(n)
    nums.foreach(println)
    // Map使用for和foreach
    val ratings = Map(
        "Lady in the Water"  -> 3.0, 
        "Snakes on a Plane"  -> 4.0, 
        "You, Me and Dupree" -> 3.5
    )
    for ((name,rating) <- ratings) println(s"Movie: $name, Rating: $rating")
    ratings.foreach {
        case(movie, rating) => println(s"key: $movie, value: $rating")
    }
    // yield关键字可以利用每次循环的返回值生成一个新的集合
    val names = List("_adam", "_david", "_frank")
    val capNames = for (name <- names) yield name.drop(1).capitalize
    println(capNames) // List(Adam, David, Frank)

  match模式匹配


    更多内容参照Scala学习(一)的模式匹配描述

    val evenOrOdd = i match {
        case 1 | 3 | 5 | 7 | 9 => println("odd")
        case 2 | 4 | 6 | 8 | 10 => println("even")
        case _ => println("some other number")
    }
    i match {
      case a if 0 to 9 contains a => println("0-9 range: " + a)
      case b if 10 to 19 contains b => println("10-19 range: " + b)
      case c if 20 to 29 contains c => println("20-29 range: " + c)
      case _ => println("Hmmm...")
    }

  异常处理

    try {
        // your scala code here
    } 
    catch {
        case foo: FooException => handleFooException(foo)
        case bar: BarException => handleBarException(bar)
        case _: Throwable => println("Got some other kind of Throwable exception")
    } finally {
        // your scala code here, such as closing a database connection
        // or file handle
    }

    Option/Some/None,正常时返回Some,异常时返回None,后续处理进行判断

    def toInt(s: String): Option[Int] = {
        try {
            Some(Integer.parseInt(s.trim))
        } catch {
            case e: Exception => None
        }
    }
    toInt(x) match {
        case Some(i) => println(i)
        case None => println("That didn't work.")
    }
    // 正常时返回Some(a+b+c),异常时返回None
    val y = for {
        a <- toInt(stringA)
        b <- toInt(stringB)
        c <- toInt(stringC)
    } yield a + b + c

    Try/Success/Failure,正常时返回Success,异常时返回Failure,后续处理进行判断

    def toInt(s: String): Try[Int] = Try {
        Integer.parseInt(s.trim)
    }
    toInt(x) match {
        case Success(i) => println(i)
        case Failure(s) => println(s"Failed. Reason: $s")
    }
    // 正常时返回Success(a+b+c),异常时返回Failure
    val y = for {
        a <- toInt(stringA)
        b <- toInt(stringB)
        c <- toInt(stringC)
    } yield a + b + c

案例对象(case objects)


  同时拥有案例类(case classes)和单例对象的特性,但是不能有参数,一般用来做枚举类型
 

  sealed trait Topping
  case object Cheese extends Topping
  case object Pepperoni extends Topping
  case object Sausage extends Topping
  case object Mushrooms extends Topping
  case object Onions extends Topping
  
  sealed trait CrustSize
  case object SmallCrustSize extends CrustSize
  case object MediumCrustSize extends CrustSize
  case object LargeCrustSize extends CrustSize
  
  sealed trait CrustType
  case object RegularCrustType extends CrustType
  case object ThinCrustType extends CrustType
  case object ThickCrustType extends CrustType
  
  case class Pizza (
      crustSize: CrustSize,
      crustType: CrustType,
      toppings: Seq[Topping]
  )

动态混入特质(Mixing traits in on the fly)

  trait TailWagger {
      def startTail(): Unit = println("tail is wagging")
      def stopTail(): Unit = println("tail is stopped")
  }
  trait Runner {
      def startRunning(): Unit = println("I'm running")
      def stopRunning(): Unit = println("Stopped running")
  }
  class Dog(name: String)
  val d = new Dog("Fido") with TailWagger with Runner
  d.startTail  // tail is wagging
  d.startRunning  // I'm running

抽象类


  Scala 也有一个抽象类的概念,类似于 Java 的抽象类。
  多数抽象类的功能都可以使用特质(trait)来实现,有下面要求的时候就得使用抽象类
    创建一个需要构造函数参数的基类
    Scala代码需要从Java代码中调用

  abstract class Pet (name: String) {
      def speak(): Unit = println("Yo")   // concrete implementation
      def comeToMaster(): Unit            // abstract method
  }
  class Dog(name: String) extends Pet(name) {
      override def speak() = println("Woof")
      def comeToMaster() = println("Here I come!")
  }

Scala集合


  ArrayBuffer


    索引的、可变的序列,类似java的ArrayList

    import scala.collection.mutable.ArrayBuffer
    val ints = ArrayBuffer[Int]()
    val nums = ArrayBuffer(1, 2, 3)
    // add one element
    nums += 4
    // add multiple elements
    nums += 5 += 6
    // add multiple elements from another collection
    nums ++= List(7, 8, 9)
    // remove one element
    nums -= 9
    // remove multiple elements
    nums -= 7 -= 8
    // remove multiple elements using another collection
    nums --= Array(5, 6)

    val a = ArrayBuffer(1, 2, 3)         // ArrayBuffer(1, 2, 3)
    a.append(4)                          // ArrayBuffer(1, 2, 3, 4)
    a.append(5, 6)                       // ArrayBuffer(1, 2, 3, 4, 5, 6)
    a.appendAll(Seq(7,8))                // ArrayBuffer(1, 2, 3, 4, 5, 6, 7, 8)
    a.clear                              // ArrayBuffer()
    
    val a = ArrayBuffer(9, 10)           // ArrayBuffer(9, 10)
    a.insert(0, 8)                       // ArrayBuffer(8, 9, 10)
    a.insertAll(0, Vector(4, 5, 6, 7))   // ArrayBuffer(4, 5, 6, 7, 8, 9, 10)
    a.prepend(3)                         // ArrayBuffer(3, 4, 5, 6, 7, 8, 9, 10)
    a.prepend(1, 2)                      // ArrayBuffer(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    a.prependAll(Array(0))               // ArrayBuffer(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    
    val a = ArrayBuffer.range('a', 'h')  // ArrayBuffer(a, b, c, d, e, f, g)
    a.remove(0)                          // ArrayBuffer(b, c, d, e, f, g)
    a.remove(2, 3)                       // ArrayBuffer(b, c, g)
    
    val a = ArrayBuffer.range('a', 'h')  // ArrayBuffer(a, b, c, d, e, f, g)
    a.trimStart(2)                       // ArrayBuffer(c, d, e, f, g)
    a.trimEnd(2)                         // ArrayBuffer(c, d, e)

  List


    线性的、不可变的序列。一个无法修改的链表。
    因为List是一个链表类,最好不要通过索引值访问大列表的元素。

    val ints = List(1, 2, 3)
    val names = List("Joel", "Chris", "Ed")
    val a = List(1,2,3)
    val b = 0 +: a  // 生成新的list,操作符引号在列表的一侧
    val c = a :+ 4  // 生成新的list,操作符引号在列表的一侧
    val d = List(-1, 0) ++: a  // 生成新的list
    val list = 1 :: 2 :: 3 :: Nil  // List(1, 2, 3)

  Vector


    索引的、不可变的序列。
    使用方法和List一样,唯一区别是用下标访问比List快

  Map


    由键和值组成的一个可迭代序列。
    Scala 有可变Map类和不可变Map类。

    import scala.collection.mutable.Map
    val states = Map("AK" -> "Alaska")
    // add one element
    states += ("AL" -> "Alabama")
    // add multiple elements
    states += ("AR" -> "Arkansas", "AZ" -> "Arizona")
    // add multiple elements from another collection
    states ++= Map("CA" -> "California", "CO" -> "Colorado"))
    // remove one element
    states -= "AR"
    // remove multiple elements
    states -= ("AL", "AZ")
    // remove multiple elements using another collection
    states --= List("AL", "AZ")
    // update
    states("AK") = "Alaska, A Really Big State"
    // iterate over Map elements
    for ((k,v) <- states) printf("key: %s, value: %s\n", k, v)
    // get the keys from a Map
    val keys = states.keys
    // get the values from a Map
    val values = states.values
    // test if a Map contains a key
    val contains3 = states.contains("AK")
    // transform Map values
    val ucMap = states.transform((k,v) => v.toUpperCase)
    // filter a Map by its keys
    val twoAndThree = states.view.filterKeys(Set(2,3)).toMap
    // take the first two elements from a Map,仅对排序Map有意义
    val firstTwoElements = states.take(2)
    // filter elements by supplying a function that operates on the keys and/or values
    states.filterInPlace((k,v) => k == "AK")

  Set


    可迭代的集合,没有重复的元素。

    import scala.collection.mutable.Set
    val set = Set[Int]()
    set += 1
    set += 2 += 3
    set ++= Vector(4, 5)
    // 尝试向已在其中的集合添加值,将被忽略
    set += 2
    // 会返回是否添加到集合中
    set.add(6)
    set -= 1
    set -= (2, 3)
    set --= Array(4,5)
    // 会返回是否删除了元素
    set.remove(2)
    set.clear()

  集合序列的常用方法


    下面的方法是集合序列类通用的
    map,filter,take,takeWhile,drop,dropWhile
      不会改变集合,返回一个带有修改结果的新集合。
    head,tail,reduce
      返回一个值

    val ints = List.range(1, 10)
    // 生成一个新的列表,每个值为原来的两倍
    val doubledInts = ints.map(_ * 2)
    // 大于5的值生成一个新的列表
    val x = ints.filter(_ > 5)
    // 偶数值生成一个新的列表
    val x = ints.filter(_ % 2 == 0)
    // 循环打印
    ints.foreach(println)
    // 返回第一个元素
    ints.head
    // 返回f
    "foo".head
    // 返回最后一个元素
    ints.tail
    // 返回r
    "bar".tail
    // 拿出前两个元素生成一个新的集合
    ints.take(2)
    // 取出从第一个开始满足条件的元素,直到遇到不满足条件的元素
    ints.takeWhile(_ < 5)
    // 扔掉前5个元素,剩下的生成一个新的集合
    ints.drop(5)
    // 扔掉从第一个开始满足条件的元素,直到遇到不满足条件的元素,剩下的生成一个新的集合
    ints.dropWhile(_ < 5)
    // 把集合中所有元素相加,最后得到一个单一值
    ints.reduce(_ + _)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值