Scala 学习笔记

文章丑一定有他的原因,这是我的学习笔记,Markdown 源码直接来源于 Typora,由于 CSS 样式及 md 解析差异,造就了这篇文章,这里只是做一份副本,不具有使用价值
———— 我自己说的

声明

val 声明必须初始化

import java.lang._ //导入lang中所有
val myStr2:String = HelloWorld!//Scala中的字符串类直接来自于java
println(myStr2)

如何输入多行代码:没输入完时可以敲回车

字面量

val i = 123
val i = true//布尔字面量

操作符

a 方法 b 等价于 a.方法(b)

递增

i += 1

富包装类

Int 对应 RichInt

String 对应 RichString, 这些类位于 scala.runtime 中

Range

1 to 5 
1.to(5)//1,2,3,4,5
1 until 5//1,2,3,4
0.5f to 5.9f by 0.8f//步长0.8f

输入输出

readInt, readShort //import scala.io.StdIn._

val str = readLine("enter your name")
val f = readFolot()
>3.5e1
println("hello");println("world!")
printf("i = %.1f",i);//print(),println(),printf()默认所有scala程序都可以使用

写入文件

import java.io.PrintWriter
val out = new PrintWriter("out.txt")
for(i <- 1 to 5) out.println(i)
out.close()

读入文件

import scala.io.Source
val in = Source.fromFile("in.txt")
val lines = in.getLines//返回迭代器
for(line <- lines) println(line)

异常处理

不接受 Java 的受检异常,将所有异常都当作不受检异常(运行时异常)

try{   
    ...
}
catch{
   case ex:FileNotFoundException => ...
   case ex:IOException => ..
}finally{
    ...
}

if表达式

与 kotlin 相同 if 表达式有值

for循环

for(变量<-表达式) 其中 变量<-表达式 被称为生成器

for(i <- 1 to 5 if i%2 == 0 ) if 被称为守卫

for(i <- 1 to 5; j <- 1 to 3) 双重循环,每个生成器都可以添加守卫

for推导式

val res = for(i <- 1 to 5) yeild {
    println(i);i//这个 i 表示把 i 的指存到新的 collection
}
r = Vector(2,4)

List

scala.collection.immutable 列表不可变,不同于java

var strList = List("a","b")

head 和 tail 方法

val otherList = "c"::strList ::是列表拼接操作符,右优先,生成新的 List,不改变旧的 list

val intList = 1::2::Nil 借助空列表 Nil 可以将多个元素串联起来初始化一个列表

Set

  • 分为 scala.collection.immutable 和 mutable
var mySet = Set("Hadoop","Spark")//默认是不可变
mySet += "Scala"//生成了新的 Set,因为 var 可以指向新的对象
import scala.collection.mutable.Set
val myMuSet = Set("a","b")
myMuSet += "c"//指针不会指向新的对象

Map

只有可变才能更新或者添加,可以使用 += 添加

scala
val un = Map("TJU"->"Tianjin")
println(un("TJU"))
if(un.contains("XMU"))
un += ("a"->"ace","int"->"Integer")

for((k,v) <- un){...}
for(k <- un.keys){...}

迭代器

val iter= Iterator("a","b")
while(iter.hasNext()){
    println(iter.next())
}
for(elem <- iter){
    println(elem)
}
  • Iterable 提供了两个方法返回迭代器 grouped 和 sliding
  • 这些迭代器返回的不是单个元素,而是元素的全部子序列
val xs = List(1,2,3,4,5)
val git = xs grouped 3//以三为步长划分 list
git.next()//List(1,2,3)
git.next()//List (4,5)
val sit = xs sliding 3//以三为长度的滑动窗口
sit.next()//List(1,2,3)
sit.next()//List(2,3,4)

Array

  • Array 类型定义的数组属于定长数组,其数组长度在初始化后就不能改变
//val arr = new Array[int](3)
val arr = Array(1,2,3)
arr(0) = 1
for(i <- 0 to 2){println(arr(i))}
//二维数组
val mx = Array.ofDim[Int](3,4)
val cb = Array.ofDim[String](3,2,4)
mx(0)(1)
  • ArrayBuffer 为可变长
val ab = ArrayBuffer(1,2,3)
ab += 4
ab.insert(2,11,22)//从第二个位置插入11,22
ab -= 2//删除第一个2
ab.remove(2)//删除第二个元素

Tuple

  • 不同类型的值的聚集
val tp = Tuple("st",1,22.5)
println(tp._1)//第一个元素
println(tp._2)//第二个元素

简单的类

new A 等价于 new A()

class A{
    private var a = 0
    def foo0():Unit = valuse += 1
    def foo1():Unit = {value += 1}
    def foo2(){value += 1}//省略了返回值和等号就不能省大括号
    def foo3():Int = {value}
}
val obj = new A
obj.foo0//没有参数可以省略括号 

编译执行

  1. 在Linux Shell 下 scala test.scala
  2. 用 Scala 解释器 ,先scala 进入解释器, 在执行:load test.scala
  • 只有符合obj结构的 scala 文件才可以使用 scalac 编译,流程语句只能出现在 main 方法中
  1. scalac test.scala
  2. scala -classpath .MyClass MyClass 是包含 main 方法的类名

    getter setter

class A{
    private var privateValue = 0//背后字段
    def value = privateValue//getter
    def value_ = (newValue:Int){//setter
        if(newValue > 0) privateValue = newValue
    }
}

构造器

  • 包含一个主构造器和多个辅助构造器
  • 辅助构造器的名称为this,每个辅助构造器必须调用一个此前已经定义好的构造器
class A{
    def this(name:String){
        this()
    }
    def this(name:String,age:Int){
        this(name)
    }
}

伴生对象

  • 当单例对象与某个类具有相同的名称时,它被称为这个类的伴生对象
  • 类和它的伴生对象必须处于同一个文件当中, 伴生对象相当于静态部分
class A{
}
object A{
    def a = 1
}

apply

  • 相当于 Kotlin 的 invoke
class A{
    def apply(){}
}
object A{
    def apply(){}
    def main(args:Array[String]){
        val a = A()//调用伴生对象的apply,像list不需要new是因为在apply中new了
        a()//调用类的apply
    }
}

update

  • 当对带有括号并包括一到若干参数的对象赋值时,编译器将调用update方法,把括号里的参数和等号右边的对象一起作为 update 的参数
val strs = new Array[String](3)
strs(0) = "big"//strs.update(0,"big")

继承

  1. 只有主构造器才可以调用超类的主构造器
  2. 在子类中重写超类的抽象方法时不需要使用 override 关键字
  3. 可以重写超类中的字段
  4. 重写一个非抽象方法必须使用 override 修饰符
abstract class A{
    val carB:String//未初始化,就是抽象字段
    def info()//无方法体,抽象方法,不需要 abstract 关键字
}

#### 特质

  • scala 中没有接口,而是提供了“特质(trait)”,不仅具备接口的功能,还具备其它特性
trait CarId{
    var id:Int
    def currentId():Int
}
class A extends CarId with otherTrait...

模式匹配

val colorStr =  colorNum match{
    case 1 => "red"
    case 2 => "green"
    //case _ => "default"
    case unexpected => unexpected + "is not allowed"//可以获取 colorNum 的值
}
for(elem <- List(1,1.2,"a")){
    val str = elem match{
        case i:Int => i + "is int"
        case s:String => s + "is String"
        case _ if(elem > 2) => "not allowed"//每个case可以加上一个守卫
        case _ => "gg"
    }

}

case类

case class Car(brand:String, price:Int)
val bc = new Car("BYD",89000)
bc match{
    case Car("BB",222) => "BB"
    case Car("BYD",89000) => "Mine"
    case Car(b,p) => b + p
}

Option类型

  • Some 是 Option 的子类
val book  =  Map("a"->1)
book.get("a")
res0:Option[Int] = Some(1)
book.get("gg")
res0:Option[Int] = None //可以使用getOrElse()

函数字面量

函数的类型如(Int)=> Int,如果只有一个参数可以省略括号 Int => Int

函数的值就是去掉类型声明如 value => {value + 1} 一个函数的值就是一个函数字面量

Lambda表达式

(参数)=> 表达式

闭包

  • 闭包也是一种函数
  • 在定义函数时会将一个自由变量变成封闭的
  • 每次调用都会生成新的闭包,每次都会保存新的活跃的外部变量
  • 即闭包可以访问函数外部的变量

占位符语法

list.filter(x => x>0)
list.filter(_ > 0)
val foo = (_:Int) + (_:Int)
foo(4,3)

发表评论

邮箱地址不会被公开。 必填项已用*标注