[关闭]
@wuzhimang 2017-08-12T15:49:43.000000Z 字数 9816 阅读 1486

Scala Tour 学习总结

博客


博客链接: http://codeshold.me/2017/07/scala_tour_note.html

因实习,需要了解数据分析方面的知识,需要学习Spark、Scala,花了一天的时间过了一下scala教程(总结即是本文),但个人推荐先从《快学Scala+中文版》这本书开始看(正在看...)这个更适合入门…… 无奈自己后知后觉了……
Tour 学习链接(自己主要是看中文):
1. TOUR OF SCALA (scala-lang.org)
2. Scala教程 (runoob.com)

基本语法

数据类型 & 变量

  1. Unit 表示无值,和其他语言中void等同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()
  2. Nothing 类型在Scala的类层级的最低端;它是任何其他类型的子类型
  3. Any 是所有其他类的超类
  4. AnyRef 类是Scala里所有引用类(reference class)的基类
  5. Byte, Short, Int 等上述的数据类型都是对象,也就是说scala没有java中的原生类型。在scala是可以对数字等基础类型调用方法的。
  6. 字面量 进一步了解

    • 浮点型字面量 0.0, 0f, 1.0e100
    • 布尔型字面量 true, false
    • 符号字面量被写成:'<标识符>这种字面量被映射成预定义类scala.Symbol的实例, 符号字面量除了显示名字之外,什么都不能做
    • '\n', "hello", """hello""" 字符、字符串、多行字符
      1. 空值是 scala.Null 类型。
        • scala.Nullscala.Nothing是用统一的方式处理Scala面向对象类型系统的某些"边界情况"的特殊类型。
        • Null类是null引用对象的类型,它是每个引用类(继承自AnyRef的类)的子类。Null不兼容值类型。
    1. val myVal : String = "Foo" // 申明常量,值不能修改
    2. var myVar : String = "Foo" // 申请变量,值可以修改
    3. // 变量类型申明
    4. var VariableName : DataType [= Initial Value]
    5. val VariableName : DataType [= Initial Value]
    6. // 变量类型引用
    7. var myVar = 10
    8. val myVal = "hello, scala!"
    9. // 多变量申明
    10. val xmax, ymax = 100
    11. val pa = (40, "Foo")
    12. --------
    13. scala> val x, y = 1, 2 // 和python不同 !!!!!!
    14. <console>:1: error: ';' expected but ',' found.
    15. val x, y = 1, 2
    16. ^
    17. scala> val x, y = (1, 2)
    18. x: (Int, Int) = (1,2)
    19. y: (Int, Int) = (1,2)
    20. scala> val x, y = 1
    21. x: Int = 1
    22. y: Int = 1

访问修饰符 & 运算符 & 控制语句

  1. Scala 访问修饰符基本和Java的一样,分别有:private,protected,public

    • 用private关键字修饰,带有此标记的成员仅在包含了成员定义的类或对象内部可见,同样的规则还适用内部类。
    • 在 scala 中,对保护(Protected)成员的访问比 java 更严格一些。因为它只允许保护成员在定义了该成员的的类的子类中被访问。而在java中,用protected关键字修饰的成员,除了定义了该成员的类的子类可以访问,同一个包里的其他类也可以进行访问
    • 作用域保护:private[x], protected[x] 这里的x指代某个所属的包、类或单例对象。如果写成private[x],读作"这个成员除了对[…]中的类(或[…]中的包中的类)及它们的伴生对象可见外,对其它所有类都是private
    1. package bobsrockets{
    2. package navigation{
    3. private[bobsrockets] class Navigator{ // 对bobsrockets中的对象都可见,其他则是private
    4. protected[navigation] def useStarChart(){
    5. class LegOfJourney{
    6. private[Navigator] val distance = 100
    7. }
    8. private[this] var speed = 200
    9. }
    10. package launch{
    11. import navigation._ // import all members
    12. object Vehicle{
    13. private[launch] val guide = new Navigator
    14. }
    15. }
    16. }
    17. }
    18. }
  2. 运算符

    1. scala> -8 >>> 1 // 无符号右移!!! 多了个这个
    2. res6: Int = 2147483644
    3. scala> 8 >>> 1
    4. res7: Int = 4
  3. 控制语句

    • if(...){...}else if(){...}else{...}
    • while(...){...};, do{...}while(...);, for(...){...}
    • for 中的 <- 用于为变量赋值, to, until, if, yield
    1. object Test {
    2. def main(args: Array[String]) {
    3. var a = 0;
    4. val numList = List(1, 2, 3, 4, 5, 6, 7)
    5. for ( a <- 1 to 10 ) {
    6. }
    7. for ( a <- 1 to 3; b <- 1 to 3) {
    8. }
    9. for ( a <- 1 until 10 ) { //不包含10
    10. }
    11. for ( a <- numList ) { // 循环集合
    12. }
    13. for ( a <- numList if a != 3; if a < 8 ) { // 循环中的过滤
    14. println("Value of a :" + a)
    15. }
    16. // 可以将for循环中的返回值作为一个变量存储
    17. var retVal = for{ a <- numList if a != 3; if a < 8 } yield a
    18. for( a <- retVal ) {
    19. println("!!!value of a :" + a)
    20. }
    21. }
    22. }

函数 & 高阶函数 & currying & 偏应用函数

  1. 基本概念

    • def functionName([para list]) : [return type] = { function body; return [expr] } , 如果不写=和方法的主体,则方法会被隐世的声明为抽象,包含它的类型于是也是一个抽象类型

      1. object add {
      2. def addInt( a:Int, b:Int ) : Int = {
      3. var sum:Int = 0
      4. sum = a + b
      5. return sum
      6. }
      7. def printMe() : Unit = {
      8. println("hello world!")
      9. }
      10. }
  2. 函数概念解析 runnob.com

    • 传名调用(call-by-name): Scala解释器支持两种--call-by-valuecall-by-name

      1. object Test {
      2. def main(args: Array[String]) {
      3. println(delay(time()))
      4. }
      5. def time() = {
      6. println("richie")
      7. }
      8. def delay(t: => Long) = { // => 设置传名调用 (放在变量名和变量类型中间)
      9. println("wfshi")
      10. t
      11. }
    • 指定函数参数名, 可变参数, 默认参数, 递归, 嵌套

      1. object Test {
      2. def main(args: Array[String]) {
      3. printInt(b=5, a=3) // 制定参数名
      4. printStrings("richie", "wf", "shi")
      5. println("F(5)" + factorial(5))
      6. println("addInt" + addInt())
      7. }
      8. def printInt(a: Int, b: Int) {
      9. println("Value of a :" + a)
      10. }
      11. // 可变参数
      12. def printStrings(args: Sting*) = {
      13. var i: Int = 0
      14. for(arg <- args) {
      15. println("Arg value" + i + arg)
      16. i += 1
      17. }
      18. }
      19. // 递归
      20. def factorial(n: BigInt): BigInt = {
      21. if (n <= 1)
      22. 1 // 无return
      23. else
      24. n * factorial(n-1)
      25. }
      26. // 默认参数值
      27. def addInt(a:Int = 5, b:Int = 7) : Int = {
      28. var sum:Int = 0
      29. sum = a + b
      30. return sum
      31. }
      32. // 函数嵌套
      33. def factorial(i: Int) {
      34. def fact(i: Int, accumulator: Int): Int = {
      35. if (i <= 1)
      36. accumulator // 无return
      37. else
      38. fact(i-1, i*accumulator)
      39. }
      40. fact(i, 1)
      41. }
  3. 匿名函数

    1. // 匿名函数
    2. var inc = (x:Int) => x+1 // 下面的简写
    3. def add2 = new Function1[Int,Int] {
    4. def apply(x:Int):Int = x+1
    5. }
    6. var x = inc(7)-1
    7. // 可定义多个函数
    8. var mul = (x: Int, y: Int) => x*y
    9. // 可以不设置参数
    10. var userDir = () => {System.getProperty("user.dir")}
  4. 高阶函数: higher-order function 操作其他函数的函数; 匿名函数

    1. object Test{
    2. def main(args: Array[String]){
    3. println(apply(layout, 10))
    4. }
    5. // 函数 f 和 值 v 作为参数,而函数 f 又调用了参数 v
    6. def apply(f: Int => String, v: Int) = f(v)
    7. def layout[A](x: A) = "[" + x.toString() + "]"
  5. 偏应用函数: 一种表达式,不需要提供函数需要的所有参数,只需要提供部分,或不提供所需参数。

    1. import java.util.Date
    2. object Test{
    3. def main(args: Array[String]) {
    4. val date = new Date
    5. // 下划线替换缺失的参数列表, 并把这新的函数值的索引赋值给变量
    6. val logWriteDataBound = log(date, _: String)
    7. logWithDateBound("message1")
    8. logWithDateBound("message2")
    9. }
    10. def log(data: Date, message: String) = {
    11. println(date + "----" + mesage)
    12. }
  6. currying 函数科里化: 将原来接受两个参数的函数变成新的接受一个参数的函数的过程

    1. def add(x:Int, y:Int) = x+y
    2. def add(x:Int)(y:Int) = x+y // currying, (y:Int)=>1+y

闭包 closure

字符串 & 数组 & 集合操作 & 迭代器

  1. 字符串 String常用方法 runoob.com

    1. val greeting:String = "Hello World!"; // 不可变
    2. val buf = new StringBuilder; buf += 'a'; // 可变
    3. "a".length
    4. "a".length()
    5. "a".concat("b")
    6. "a" + "b"
    7. printf("%s %d"...) // 格式化输出
  2. 数组 常用方法

    1. var z:Array[String] = new Array[String](3)
    2. var z = new Array[String](3)
    3. z(0) = "richiewfshi"; z(1) = "richie"; z(2) = "wfshi"
    4. var z = Array("richie", "wf", "shi")
    5. z.length
    6. // 多维数组
    7. var richieMatrix = ofDim[Int](3,3)
    8. richieMatrix(i)(j) = "xx"
    9. var my = concat(mylist1, mylist2)
    10. import Array._
    11. var mylist3 = range(1, 100, 50)
    12. // 使用数组方式之前需要 import Array._
  3. 集合操作
    针对不可变集合类的每次操作都会返回一个新的集合,同时使原来的集合不发生改变

    1. val x = List(1, 2, 3, 4)
    2. val x = Set(1, 3, 5, 7)
    3. val x = Map("one" -> 1, "two" -> 2, "three" -> 3) // !!!
    4. scala> val mymap = {"key1" -> 1; "key2" -> 2}
    5. mymap: (String, Int) = (key2,2)
    6. val t = new Tuple3(1, 3.14, "richie") //Tuple3[Int, Int, String]类型,支持的元组最大长度为22
    7. val t = (1, 3, "wfs")
    8. // Tuple.productIterator() 迭代输出元组的所有元素
    9. t.productIterator.foreach(i => println("Value = " + i)
    10. (1, 2, "swf").toString // Tuple.toString() 将元素组合成一个字符串
    11. (1, 2).swap
    12. val sum = x._1 + x._2
    13. val x:Option[Int] = Some(5) // 定义Option, Option[T] 表示有可能包含值的容器,也可能不包含值。
  4. 迭代器
    Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法。常用方法

    1. val it = Iterator("richie", "wf", "shi") // 用于检测集合中是否还有元素。
    2. while(it.hasNext) {
    3. println(it.next()) // 返回迭代器的下一个元素,并且更新迭代器的状态。
    4. }
    5. val itmax = it.max
    6. val itmin = it.min
    7. val itlen = it.length
    8. val itsize = it.size
  5. Option
    Scala Option(选项)类型用来表示一个值是可选的(有值或无值)。
    Option[T] 是一个类型为 T 的可选值的容器: 如果值存在, Option[T] 就是一个 Some[T] ,如果不存在, Option[T] 就是对象 None常用方法

    1. val myMap: Map[String, String] = Map("key1" -> "value")
    2. val value1: Option[String] = myMap.get("key1") // Some("value")
    3. val value2: Option[String] = myMap.get("key2") // None
    4. // 通过模式匹配来输出匹配值
    5. val res = show(myMap.get("key1"))
    6. def show(x: Option[String]) = x match {
    7. case Some(s) => s
    8. case None => "?"
    9. }
    10. val a:Option[Int] = Some(5)
    11. val b:Option[Int] = None
    12. b.getOrElse(0); b.getOrElse(5) // 都返回默认值5
    13. a.isEmpty

类和对象 & Trait

  1. 类和对象

    • Scala继承一个基类跟Java很相似, 但我们需要注意以下几点:

      1. 重写一个非抽象方法必须使用 override 修饰符。
      2. 只有主构造函数才可以往基类的构造函数里写参数。
      3. 在子类中重写超类的抽象方法时,你不需要使用override关键字。
      1. class Location(override val xc: Int, override val yc: Int,
      2. val zc: Int) extends Point(xc, yc) {
      3. ...
      4. }
      5. // Scala重写一个非抽象方法,必须用override修饰符
      6. class Employee extends Person {
      7. var salary = 0.0
      8. override def toString = super.toString + "[salary=" + salary + "]"
      9. }
    • 当单例对象与某个类共享同一个名称时,他被称作是这个类的伴生对象:companion object。必须在同一个源文件里定义类和它的伴生对象。类被称为是这个单例对象的伴生类:companion class。类和它的伴生对象可以互相访问其私有成员。
  2. Trait(特征)

    • Scala Trait(特征) 相当于 Java 的接口,实际上它比接口还功能强大,与接口不同的是,它还可以定义属性和方法的实现
    • Scala的类只能够继承单一父类,但是如果是 Trait(特征) 的话就可以继承多个,从结果来看就是实现了多重继承

      1. trait Equal {
      2. def isEqual(x: Any): Boolean
      3. def isNotEqual(x: Any): Boolean = !isEqual(x)
      4. }
      5. class Point(xc: Int, yc: Int) extends Equal {
      6. var x: Int = xc
      7. var y: Int = yc
      8. def isEqual(obj: Any) =
      9. obj.isInstanceOf[Point] &&
      10. obj.asInstanceOf[Point].x == x
      11. }
      12. object Test {
      13. def main(args: Array[String]) {
      14. val p1 = new Point(2, 3)
      15. val p2 = new Point(2, 4)
      16. println(p1.isNotEqual(p2))
      17. }
      18. }
    • 特征也可以有构造器,由字段的初始化和其他特征体中的语句构成。这些语句在任何混入该特征的对象在构造是都会被执行。
    • 构造器的执行顺序:
      1. 调用超类的构造器;
      2. 特征构造器在超类构造器之后、类构造器之前执行;
      3. 特征由左到右被构造;
      4. 每个特征当中,父特征先被构造;
      5. 如果多个特征共有一个父特征,父特征不会被重复构造
      6. 所有特征被构造完毕,子类被构造。
  3. 提取器是从传递给它的对象中提取出构造该对象的参数。

    • Scala 提取器是一个带有unapply方法的对象。unapply方法算是apply方法的反向操作:unapply接受一个对象,然后从对象中提取值,提取的值通常是用来构造该对象的值。 链接

模式匹配 & 正则表达式

文件I/O & 异常处理

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注