• scala基础


    类型

    1.基本类型

    和Java类似,scala也有基本类型,但是scala的基本类型也是对象,String类型是直接引用的Java的string,举个栗子(scala脚本):

    scala> val num = 2 + 3
    num: Int = 5
    
    //等价于
    scala> val num = (2).+(3)
    num: Int = 5
    

    基本操作符都是方法,定义在scala.基本类型里面,比如+ - * / ,也有一些稍微复杂的操作定义在富包装类中,以‘Rich+基本类型定义’,比如max min等

    可变和不可变对象

    函数式语言强调对象不可变,方法无副作用。

    用val定义不可变对象,不可变对象初始化值时需要赋初值。

    用var定义可变对象,可随时赋值

    类型推演

    三目运算符

    Java:a > b ?a : b

    scala: if(a>b) a else b

    控制结构

    for循环生成器

    java: for(int i=1; i<=5; i++)

    scala:for(i <- 1 to 5 by 1)

    for守卫表达式

    java: for(int i=1; i<=5 && i%2 == 0; i++)

    scala: for(i <- i to 5 by 1 if i%2 == 0)

    for推导式

    var arr = for(i <- 1 to 5 by 1 if (i%2) == 0) yield{ println(i); i}

    异常

    java:

    try{} 
    catch(NullPointerException e1){}
    catch(FileNotFoundException e2){}
    finally{}
    

    scala:

    try{} 
    catch{
    	case e1:NullPointerException => {}
    	case e2:FileNotFoundException => {}
    	} 
    finally{}
    

    break and continue

    import util.control.Breaks._
    
    var arr = Array(1,3,9,5)
        breakable {
          for (i <- arr)
            if (i > 5) break
            else println(i)
        }
        
        println("continue...")
        //continue语句
        for (i <- arr)
          breakable{
            if (i> 5) break
            else println(i)
          }
    

    模式匹配

    1.Java的switch case语句,同时也支持守卫,和for循环类似

    var num = 10;
        num match {
          case _ if(num % 2 == 0) => println("偶数")
          case _ if(num %2 != 0) => println("奇数")
          case _ => println("default")
        }
    

    2.case类
    case类是经过优化的类,会自动重载很多有用的方法比如:toString、equals、hashcode ,更重要的是,case类会自动生成伴生对象(object classname;apply方法)

    数据结构

    数组

    //定义
    var arr = Array(1,2,3)
    var arr = new Array[Int](3)
    //赋值
    arr(0) = 12
    //二维数组
    var arr = Array.ofDim[Int](3,4)
    arr(0)(1) = 10
    

    元组

    不同类型的数据的集合

    val tuple = ("learn scala",56.2)
    println(tuple._1+":"+tuple._2)
    

    容器

    可变容器和不可变容器.常见的List、Vector是不可变容器,Map、Set等既有可变的,也有不可变得

    import scala.collection.immutable._
    import scala.collection.mutable._
    

    序列

    List的定义和使用

    //list1和list2的内容不可变
    var list1 = List(1,2,3)
    //Nil是一个空链表,list2=List(4,5,6)
    var list2 = 4::5::6::Nil
    var list3 = 7::8::list1
    

    Vector

    var vector = Vector(3, 4)
    //向前添加
    println(1 +: 2 +: vector)
    //向后添加
    println(vector :+ 5 :+ 6)
    

    Range

    Range是一种带索引的不可变等差数列,上面的1 to 5 by 1就是一个Range对象

    包含起点,不包含终点的range:1 until 5 by 1

    Set和Map

    Set:var set = Set("Apache","Hadoop","Spark")

    Map:var map = Map(1->"first",2->"Second")

    迭代器

    类和方法

    方法

    定义方式:def 方法名(参数名:参数类型, 参数名:参数类型,......):返回值类型 = {方法体}

    简写方式:

    1. 无参数可以不加方法名后面的括号;
    2. 返回值类型也可以不写,通过推演得出;
    3. 方法体如果只有一句话,也可以不写花括号;
    4. 最后的返回值可以不写return关键字。
    5. 在类中定义的方法,可以使用中缀表示法简写

    比如:def print = println("Hello Wolrd")

    类的定义:
    和Java类似的定义类的方式

    访问权限:public(默认访问方式)、private、protected。当属性为private访问属性时,一般都会提供get和set方法,scala的getter和setter定义方式如下

    class Person(var name:String){
      private var _age = 0
      def age = _age
      def age_=(a:Int) = _age = a
    }
    

    构造器

    定义主构造器:class 类名(var|val 属性名:类型......)
    定义在主构造器的和在类内部声明为public访问权限的属性都默认提供了getter和setter方法,以对象名.属性名的方式访问
    例如

    scala> class Counter(var count:Int)
    defined class Counter
    scala> var counter = new Counter(10)
    counter: Counter = Counter@435a2c7d
    //访问
    scala> println(counter.count)
    10
    

    定义辅助构造器:def this(参数列表){}

    第一个辅助构造器必须依赖主构造器,第二个辅助构造器必须依赖于第一个辅助构造器,以此类推。例如:

    class Person() {
      private var _age = 0
      private var _name = ""
    
      def this(age: Int) {
        this()
        _age = age
      }
    
      def this(age: Int, name: String) {
        this(age)
        _name = name
      }
    }
    

    对象

    1.伴生对象和孤立对象

    伴生对象是伴生类的单例对象,没有定义伴生类的单利对象称为孤立对象。伴生对象的定义方式为:

    //object People是class People的伴生对象,也是单例对象。同时在伴生对象中还可以实现static关键字,因为一个类只能生成一个伴生对象,而在伴生对象中定义的public方法和属性就是static的
    class People{}
    
    object People{
    def eat = {println("people eat")}
    }
    
    //call
    People.eat()
    
    

    2.apply方法

    apply定义在伴生对象中,可以通过类名.apply()形式调用,但是也可以省略apply,直接类名+参数的形式调用。apply方法可以重载

    class Animal(name:String){
    }
    
    object Animal{
      def apply(param:String) = new Animal(param)
    }
    
    //call
    val dog = Animal("dog")
    

    3.unapply方法

    unapply方法同apply方法一样定义在伴生对象中,不同的是,unapply用于提取类的属性

    class Animal(val name:String){
    }
    
    object Animal{
      def apply(param:String) = new Animal(param)
      def unapply(a :Animal) :Option[(String)] = Some((a.name))
    }
    
    //call
    val Animal(name) = Animal("dog")
    //name属性的值被提出来
    println("animal's name="+name)
    

    类和特质

    抽象类

    抽象类需要加abstract关键字,在类中定义的属性不赋初值,即为抽象字段;方法不定义方法体为抽象方法
    扩展类通过关键字extend继承抽象类,其中,抽象类和抽象字段可以不使用override关键字修饰,但是抽象类里面的非抽象方法必须通过关键字abstract实现

    abstract class AbsCar {
      val name:String
      def print():Unit
      def geeting = println("welcome to my car")
    }
    
    class BMWCar extends AbsCar {
      val name: String = "BMW"
    
      def print: Unit = println("car name is " + name)
    
      override def geeting: Unit = super.geeting
    }
    

    option类

    在返回值可能为null的情况下,尽可能将返回值包装为Option类型,这样,在获取返回值的时候,可以使用getOrElse方法获取一个默认对象,而不是判断是否为空或者出现nullPointExcption

    trait特质

    使用trait声明一个特质,特质和接口类似。
    当只有一个基类需要继承,或者只有一个trait需要混入时,子类使用extend关键字。但是当有多个特质需要混入时,应该extend后加with关键字,声明需要混入的特质

    函数

    在面向过程(C语言)和面向对象(C++、Java)的编程语言中,值、结构体、对象是可以赋值传递的。在函数式语言中,函数也是可以通过赋值来传递的,类似于C的函数指针,但是更强大

    函数变量

    方法(函数)定义:

    def counter(num:Int):Int  = num + 1
    

    和变量的定义相似,函数也有类型和值。参数类型Int+返回值类型Int构成了函数的类型,函数的值就是入参num+函数体。由此,我们可以这样定义一个函数:

    //变量名num:变量类型Int = 变量值10
    val num:Int = 10
    //变量名counter:变量类型(Int => Int) = 变量值(value) => {value+1}
    val counter:(Int => Int) = (value) => {value+1}
    

    lambda表达式

    函数有匿名函数,就是无需定义函数名的函数,也就是lambda表达式。

    匿名函数的定义:(参数名:参数类型,参数名:参数类型...) => {函数体}

    (value:Int) => {value/2}
    

    下划线

    _标识那些在函数中只出现一次的变量,比如:

    //等价于lambda表达式:(value:Int) => value+1
    (_:Int) + 1
    

    高阶函数

    //2的x次方
    def powerOfTow(x: Int): Int = if (x <= 0) 1 else x * powerOfTow(x - 1)
    
    //l+(l+1)+...r
    def sumInts(l: Int, r: Int): Int = if (l > r) 0 else l + sumInts(l + 1, r)
    
    //l的平方+(l+1)的平方+..+r的平方
    def sumSequars(l: Int, r: Int): Int = if (l > r) 0 else l * l + sumSequars(l + 1, r)
    
    //2的l次方+2的(l+1)次方+...+2的r次方
    def sumPowerofTwo(l: Int, r: Int): Int = if (l > r) 0 else powerOfTow(l) + sumPowerofTwo(l + 1, r)
    
    //高阶函数,参数也是函数
    def sum(f: Int => Int, l: Int, r: Int): Int = if (l > r) 0 else f(l) + sum(f, l + 1, r)
    
    println(sum(x => x, 1, 5))
    println(sum(x => x * x, 1, 5))
    println(sum(powerOfTow, 1, 5))
    

    容器的遍历和映射

    val f = println(_:Int)
    val list = List(1,2,3)
    list.foreach(f)
    println(list.map(a => a * 2))
    
    val strs = List("Apache","Hadoop","spark")
    println(strs.flatMap(a => a.toList))
    

    filter和reduce

    val list = List(1, 2, 3, 4, 5);
    println(list.filter(i => i%2 == 0))
        
    println(list.reduce((a,b) => a+b))
    println(list map (_.toString) reduce ((x, y) => s"f($x,$y)"))
    
    println(list reduceLeft (_ - _))
    println(list reduceRight (_ - _))
    println(list.fold(10)(_ * _))
    
  • 相关阅读:
    No-3.Linux 终端命令格式
    No-2.常用 Linux 命令的基本使用
    No-1.文件和目录
    No-7.运算符
    No-6.If语句
    No-5.变量的命名
    YOLOv4详细分析 | 细数当前最佳检测框架小细节(附论文及源码下载)
    案例】S7-200SMART 实时时钟如何在MCGS触摸屏上显示并写入
    卡尔曼滤波:从入门到精通
    mmdetection最小复刻版(七):anchor-base和anchor-free差异分析
  • 原文地址:https://www.cnblogs.com/boboshenqi/p/10995292.html
Copyright © 2020-2023  润新知