第1章 基础

  1. 调用函数和方法
  • 调用函数,以math包中的函数调用为例
    import scala.math._ "_"相当于java中的*
    pow(2, 4) 返回16.0。如果是scala开头的包,可以省略scala
  • 方法,scala中没有静态方法
    与之对应的是每一个类都有一个同名的伴生对象,定义在伴生对象中的方法可以直接调用
    类的构造方法可以使用伴生对象中的apply方法
    例如Array(1,2,3,4),其实调用的是Array.apply(1,2,3,4) 。

第2章 控制结构和函数

  1. 条件表达式
    val b:Any = if (condition) 1 else "abc"
    如果是if(condition) 1 <=> if (condition) 1 else () 返回类型是AnyVal
    Unit用"()"表示。AnyVal继承Any

  2. 语句的终止,可以使用Breaks,最好是使用while循环,通过标志位来终止循环

  3. 高级for循环和for推导式
    for循环中可以放多个生成式,每个生成式可以带一个守卫。
    例子: for(i<- 0 to 3 if i%2!=0; j<- 1 to 10 if j !=4)
    for循环中定义任意多的变量在循环中使用
    例子:for(i<- 0 to 3; from = 4 - i; j <- from to 10)
    for推导式
    例子: val cc=for(i<- 0 to 3) yield i*2 返回cc:Seq[Int]=Vector(0, 2, 4, 6)
    cc的类型和for中的第一生成式有关

  4. 函数
    函数定义,必须有=号。除非是递归调用的方式,不然不用声明返回值的类型
    def sum(a:Int,b:Int) = {
    a + b
    }
    +方式是Int隐式转换成RichInt之后的方法

  5. 可变参数
    可变参数
    def sum(args: Int) = {
    //方法体里面使用的时候args变成了Seq
    //如果是递归调用,直接将args传进去则会失败
    sum(args.tail: _
    )//将Seq转成可变参数传入
    //tail的意思是除第一个元素后的序列
    }

  6. 过程
    不带=号,没有返回值,那就是过程
    def process(i: Int){
    //这就是一个过程
    }

  7. 懒值,在使用的时候才进行初始化
    lazy val b=//操作开销比较大的资源

  8. 异常捕获
    try{
    //
    }catch{
    case e1:NPE => {}
    case _ => {}
    }
    //通过模式匹配的方式来捕获不同的异常

第3章 数组相关操作

  1. 定长数组
    Array("a","b")相当于java中的String[]
    ArrayString 长度为10的定长数组
    访问元素arr(0)

  2. 变长数组:数组缓冲
    ArrayBuffer("10","9")
    val s = ArrayBufferString
    数组尾端添加或者删除值都可以,且是一个高效的操作
    s += "abc"
    s ++= Array("g", "h")
    s.trimEnd(5) 尾端移除5个元素
    Array转ArrayBuffer和ArrayBuffer转Array
    s.toArray.toBuffer

  3. 遍历数组和缓冲数组
    for(elem <- elems)
    for (i <- 0 until elems.length) 遍历数组的索引
    for(i <- 0 until (elems.length,2)) 调着遍历索引
    for(i <- (0 until elems.length).reverse) 倒着遍历索引

  4. 练习,移除数组中第一个负数后面的所有负数
    代码逻辑:
    def main(args: Array[String]): Unit = {
    //移除数组中第一个负数之后的所有负数
    val ints = ArrayBuffer(1, -1, 1, 2, -3, 3, -2, -5, 0)
    var first = true
    //获取到所有的索引
    val indexes = for (i <- 0 until ints.length if first || ints(i) >= 0) yield {
    if (ints(i) < 0) first = false;i
    }
    //将满足条件的元素放到数组的前端,因为indexes(j)的值大于等于j,所以往前移的过程中,后面的值不会被覆盖
    for (j <- 0 until indexes.length) ints(j) = ints(indexes(j))
    ints.trimEnd(ints.length-indexes.length)
    println(ints)
    }

  5. 创建多维数组
    //创建规则的多维数组,3行4列的二维数组
    val doubleArray = Array.ofDimInt
    //创建不规则的多维数组,10行,每行数组的长度不确定的二维数组
    val arr = new ArrayArray[Int]
    for (i <- arr.indices) {
    arr(i) = ArrayInt
    }
    //i是形参,在for的代码块中是不允许变更的。下面这种方式是错误的
    for (elem <- arr) {
    elem = new ArrayInt
    }//编译失败的代码
    //因为没有apply方法适用,所以用new的方式创建

  6. scala和java的互转
    //集合的隐式转换,如果调用java的api需要传List
    import scala.collection.JavaConversions.bufferAsJavaList
    val list=ArrayBuffer(1,2,3)
    list.add(5)//适用java集合的方法添加元素
    //java List转scala的Buffer
    import scala.collection.JavaConversions.asScalaBuffer
    val list1 = new util.ArrayListString
    list1 += "a"
    println(list1)

第4章 映射和元组

  1. 映射的创建,可以创建hash映射和树映射
    创建不可变的映射
    Map("a"->1, "b"->2)
    创建可变的映射
    scala.collection.mutable.Map("a" -> 1, "b" -> 2)
    创建一个空的可变映射,需要指定映射的方式
    scala.collection.mutable.HashMapString,Int

  2. 获取映射中的值
    map("a")直接获取的方式可能会报错
    Exception in thread "main" java.util.NoSuchElementException: key not found: c
    正确的调用方式,get()调用返回Option进行模式匹配Some或者None 或者getOrElse("a",3)给默认值

  3. 更新映射中的值
    为可变map添加值
    mm += ("b" -> 3) //如果key已经存在,则修改
    mm -= "c" //移除对应的key
    mm ++= Map("d" -> 4)
    mm --=Seq("d","a")

  4. 迭代映射
    for ((k,v) <- mm)
    反转映射
    val newmm=for((k,v)<- mm if k!="a") yield (v,k)

  5. 排序映射
    scala默认的是Hash映射,如果想要使用树结构的映射,需要key有序。scala只有一种不可变的Map
    val sortMap = scala.collection.immutable.SortedMapInt,String

    还有一种方式,就是使用java的TreeMap来实现有序的映射。
    如果按照插入的顺序访问映射,使用scala.collection.mutable.LinkedHashMap
    
  6. 与java的互转
    import scala.collection.JavaConversions.mapAsScalaMap
    import scala.collection.JavaConversions.mapAsJavaMap

  7. 使用模式匹配获取元组的值
    //模式匹配的方式获取元组的值
    val t = (1, 2, "a", "b")
    val (f, second, _, _) = t
    _只是一个占位符,不使用

  8. 拉链操作
    Array("a","b").zip(Array(1,2)).toMap

第5章 类

  1. 简单的类和无参方法
    //scala不使用这种定义方式
    class Counter{
    private var i =0
    def increment(): Unit ={
    i+=1
    }
    def current=i
    }

    //改变状态的方法Increment
    //获取值的方法,去掉了()
    
    class Counter{
      var age=0
    }
    
    编译的时候自动创建setter和getter方法
    getter方法是age(),counter.age调用,省略了()
    setter方法是age_=(参数),counter.age_=(1)调用,也可以重新setter方法
    
    class Counter{
      private var privateAge:Int=0
      def age=privateAge
      def age_=(): Unit ={
        //set逻辑
      }
    }
    和java一样定义setter和getter方法
    

    如果把属性声明成private,则scala编译成java程序的时候setter和getter方法都声明成private的
    如果属性声明成val,只有getter方法生成
    如果不想要setter方法和getter方法,属性声明成private[this]

  2. 私有字段的访问
    private修饰符
    class Counter{
    private var privateAge:Int=0
    def age=privateAge
    def age_=(): Unit ={
    //set逻辑
    }
    }

    类中能访问对象的私有属性包括非this对象的私有属性
    class Counter{
      private var privateAge:Int=0
      def age=privateAge
      def age_=(): Unit ={
        //set逻辑
      }
      def compare(other:Counterr){
          other.privateAge也是能访问的
      }
    }
    
    如果只想当前对象能访问私有属性,则使用private[this]来进行修饰
    如果private[otherCounnter]修饰Counter的私有属性,如果指定其他类的类名,那么其他类中也可以访问Counter对象的私有属性
    
  3. scala类编程javaBean
    @BeanProperty
    var name:String=_
    为属性增加注解,自动生成setName方法和get方法,变量不能声明成private
    总共生成4个方法
    name
    name_=(name:String)
    setName(name:String)
    get()

  4. 辅助构造器
    class Counter(address:String){
    private var privateAge:Int=0
    privateAge = 1
    @BeanProperty
    var name:String=_
    def this(name:String,address:String){
    this(address)
    this.name=name
    }
    def this(name:String,other:String,address:String){
    this(name,address)
    this.name+=other
    }
    }

    辅助构造器必须调用主构造器,第二个辅助构造器其实也是调用了主构造器
    class Counter(val address:String,private var tt:String)
    主构造器中可以使用修饰符val、var、private,如果不声明,默认是val
    加了修饰符,参数会被声明成属性。
    如果没有修饰符,方法中使用了参数,也会被声称属性。如果没有使用,只是访问,不会被声明成字段
    
    禁止调用主构造器
    class Counter private(address:String)
    
    这样只能调用辅助构造器了嵌套类
    
  5. 嵌套类
    嵌套类,类中可以嵌套类,函数中可以嵌套函数,对象中可以嵌套类

第6章 对象

  1. 单例对象,定义一个object就是一个单例对象,对象在首次使用的时候构造出来

  2. 伴生对象,伴生对象和伴生类可以互相访问私有属性,前提是声明在同一个源文件中
    类访问伴生对象中的私有方法的时候,必须类名.方法名的方式调用,不能直接方法名调用,因为方法不在同一个域中

  3. 扩展类或特质的对象
    abstract class AbstractNothing(des:String){
    def a()
    def b()
    }

    object ImplNothing extends AbstractNothing("nothing")
    {
      override def a(): Unit = {println("aaa")}
    
      override def b(): Unit = {
        println("bbb")
      }
    }
    
    
    class Counter(address:String){
      private var privateAge:Int=0
      @BeanProperty
      var name:String=_
      def this(name:String,address:String){
        this(address)
        this.name=name
      }
      def this(name:String,other:String,address:String){
        this(name,address)
        this.name+=other
      }
    }
    
    object ImplNothing2 extends Counter("address")
    {
    //只能访问到非private的属性和方法
      ImplNothing2.name
      ImplNothing2.setName("a")
    }
    
  4. 枚举对象
    //枚举对象
    object EnumColor extends Enumeration {
    // val GREEN, RED, BLUE = Value
    //调用value方法返回一个Value的实例
    val GREEN=Value(0,"abc")
    val RED=Value(1,"abc")
    val BLUE=Value(2,"abc")
    //为枚举实例定义id和name,如果没有定义id就是前面一个的id+1,如果前面没有那就从0开始
    //name没有定义那就是GREEN作为name
    }
    object TestH{
    def main(args: Array[String]): Unit = {
    val blue: EnumColor.Value = EnumColor.BLUE
    }
    }

第7章 包和引入

第8章 继承

  1. 类型检查和转换
    if (blue.isInstanceOf[EnumColor.Value]) {
    val newBlue=blue.asInstanceOf[EnumColor.Value]
    }

      //如果要准确判断是不是一个类的对象
        if (blue.getClass == classOf[Counter]) {
            
        }
        
       最优的方法是使用模式匹配,优于类型检查和转换
           blue match {
          case a: Counter => {
    
          }
          case _ => {
    
          }
        }
    
  2. 典型构造顺序和提前定义的问题
    object Demo02 {
    def main(args: Array[String]): Unit = {
    val et = new Class2()
    val arr = et.env
    println(arr.length) //打印的结果是0
    }

    }
    class Class1{
      val arraySize=10
      val env:Array[String]=new Array[String](arraySize)
    }
    
    class Class2 extends Class1{
      override  val arraySize=2
    }
    
    解释,先调用父类的构造方法,父类初始化arraySize,此时创建env,想要获取arraySize,调用方法arraySize(),但是这个方法已经被重写(重写了字段,就是重写了getter方法),这是调用子类的方法arraySize(),返回子类的arraySize,此时子类的arraySize还没有初始化成2。所有的int值,在分配
    空间的时候都会被初始化成0,所以得到的数组长度为0
    
    采用提前定义的方式来解决这个问题
    先初始化子类中的某些字段
    class Class2 extends {
      override val arraySize = 2
    } with Class1{
    }
    
  3. scala继承层级
    与java中基本类型对应的类和Unit类都是继承AnyVal
    其他类都是继承AnyRef,相当于java中的Object
    AnyRef和AnyVal都是继承自Any

第9章 文件和正则表达式

  1. 后面补充

第10章 特质

  1. 后面补充
内容来源于网络如有侵权请私信删除

文章来源: 博客园

原文链接: https://www.cnblogs.com/jeasonchen001/p/13586727.html

你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!