zoukankan      html  css  js  c++  java
  • scala 笔记

    如果操作列表的话, 请使用 ListBuffer  如:

     val lstBuf = mutable.ListBuffer[String]()

    lstBuf += "111"

    lstBuf += "22"

     

    lstBuf += ("abab", "ddd", "ddd")

    lstBuf.toList.foreach(println(_))

     

     


     

    常用表达式

    if表达式

    val isAdult = if (age > 18) 1 else 0

     

    循环

    while(true) {}

    for(i <- 1 to n) {} //[1,n]

    for(i <- 1 until n) {} //[1,n)

    for(i <- (1 until n).reverse) //反向遍历

    for(c <- "Hello World") print(c)

    for(i <- 1 to 9; j <- 1 to 9) {}

    for(i <- 1 to 100 if i % 2 == 0) println(i) //if守卫

    for(i <- 1 to 3) yield i //推导式:构造集合Vector(1, 2, 3)

     

    异常,与java类似

    try {

        throw new IllegalArgumentException("")

    } catch {

        case exception: IllegalArgumentException => println(exception)

    } finally {

    }

     


     

     

    ·apply函数

        ·Scala中的apply函数是非常特殊的一种函数,在Scala的object中,可以声明apply函数。而使用“类名()”的形式,其实就是“类名.apply()”的一种缩写。通常使用这种方式来构造类的对象,而不是使用“new 类名()”的方式。

        ·例如,"Hello World"(6),因为在StringOps类中有def apply(n: Int): Char的函数定义,所以"Hello World"(6),实际上是"Hello World".apply(6)的缩写。

        ·例如,Array(1, 2, 3, 4),实际上是用Array object的apply()函数来创建Array类的实例,也就是一个数组。

     

    breakable

     

    import scala.util.control.Breaks._

     

    breakable({

      for (i <- 0 until(10)){

        if(i==7) break()

        println(i)

      }

    })

     

    any 类型 ()  AnyVal=()

     

     

    ====

    val ages = Map("Leo" -> 30, "Jen" -> 25, "Jack" -> 23)

    ages("Leo") = 31  错误: map 是不可变的,里面的值也无法修改

    Map 元素的获取, 要使用getOrElse, 直接获取不到时会报异常

    ages.getOrElse("leo","default")

     

    // 增加多个元素

    ages += ("Mike" -> 35, "Tom" -> 40)

    // 移除元素

    ages -= "Mike"

    // 更新不可变的map

    val ages2 = ages + ("Mike" -> 36, "Tom" -> 40)

    // 移除不可变map的元素

    val ages3 = ages - "Tom"

     

    SortedMap, LinkedHashMap

    // SortedMap可以自动对Map的key的排序

    val ages = scala.collection.immutable.SortedMap("leo" -> 30, "alice" -> 15, "jen" -> 25)

     

    // LinkedHashMap可以记住插入entry的顺序

    val ages = new scala.collection.mutable.LinkedHashMap[String, Int]

    ages("leo") = 30

     

     

    Scala的getter和setter方法的命名与java是不同的,是field和field_=的方式

     

    ========

    传入可变变量

    val s = sum(1 to 5: _*)

      

    在Scala中,提供了lazy值的特性,也就是说,如果将一个变量声明为lazy,则只有在第一次使用该变量时,变量对应的表达式才会发生计算。这种特性对于特别耗时的计算操作特别有用,比如打开文件进行IO,进行网络IO等。

     

    import scala.io.Source._

    lazy val lines = fromFile("C://Users//Administrator//Desktop//test.txt").mkString

    即使文件不存在,也不会报错,只有第一个使用变量时会报错,证明了表达式计算的lazy特性。

     

     

    函数没有返回值的成为过程,如:

    def fnTest(name: String) {

      print(name)

    }

     

    ====

    object通常用于作为单例模式的实现,或者放class的静态成员,比如工具方法

     

    ==伴生类, 伴生对象

    object通常用于作为单例模式的实现,或者放class的静态成员,比如工具方法

    object 对象也可以继承抽象方法

    // 伴生类和伴生对象必须存放在一个.scala文件之中

    // 伴生类和伴生对象,最大的特点就在于,互相可以访问private field

     

    ==函数传参

    • 传值调用(call-by-value):先计算参数表达式的值,再应用到函数内部;
    • 传名调用(call-by-name):将未计算的参数表达式直接应用到函数内部

    在进入函数内部前,传值调用方式就已经将参数表达式的值计算完毕,而传名调用是在函数内部进行参数表达式的值计算的。

    这就造成了一种现象,每次使用传名调用时,解释器都会计算一次表达式的值。

     

    参数形式: def delayed( t: => Long ) = {}

    =>之前为空 ,不指定类型

     

    ========类内部定义的是方法

     

    求为field选择合适的修饰符就好:var、val、private、private[this]

      

    ====使用类似 java getter, setter

    class  Person2(@BeanProperty var name:String){}

     

    val p= new Person2("nihao")

    p.getName

    p.setName("22")

     

    ==内部类: 

    但是与java不同的是,每个外部类的对象的内部类,都是不同的类

    demo: 

    class Class {

      val students = new ArrayBuffer[Student]();

      class Student(@BeanProperty val name: String) {

      }

     

      def newStudent(name: String): Student = {

        new Student(name)

      }

    }

     

    val class1 = new Class;

    val class2 = new Class;

     

    val s1 = class1.newStudent("name1")

    class1.students += s1;

     

    val s2 = class2.newStudent("name2")

     

     

    ==========isInstanceOf, asInstanceOf , getClass, classOf

    需要使用isInstanceOf判断对象是否是指定类的对象,如果是的话,则可以使用asInstanceOf将对象转换为指定类型

    isInstanceOf只能判断出对象是否是指定类以及其子类的对象,而不能精确判断出,对象就是指定类的对象

    // 如果要求精确地判断对象就是指定类的对象,那么就只能使用getClass和classOf了

     

     

    ==继承

    跟java一样,scala中同样可以使用protected关键字来修饰field和method,这样在子类中就不需要super关键字,直接就可以访问field和method

    // 还可以使用protected[this],则只能在当前子类对象中访问父类的field和method,无法通过其他子类对象访问父类的field和method

     

    --调用父类的 constructor

     

    class Person(val name: String, val age: Int)

    class student(name: String, age: Int, val score: Int) extends Person(name, age) {

      def this(name: String) {

        this(name, 0, 0)

      }

      def this(score: Int) {

        this("abc", 0, score)

      }

    }

     

    // Scala中,每个类可以有一个主constr uctor和任意多个辅助constructor,而每个辅助constructor的第一行都必须是调用其他辅助constructor或者是主constructor;因此子类的辅助constructor是一定不可能直接调用父类的constructor的

    // 只能在子类的主constructor中调用父类的constructor,以下这种语法,就是通过子类的主构造函数来调用父类的构造函数

    // 注意!如果是父类中接收的参数,比如name和age,子类中接收时,就不要用任何val或var来修饰了,否则会认为是子类要覆盖父类的field

     

    ==匿名内部类

     

    匿名子类,也就是说,可以定义一个类的没有名称的子类,并直接创建其对象,然后将对象的引用赋予一个变量。之后甚至可以将该匿名子类的对象传递给其他函数。

     

    class Person(protected val name: String) {

      def sayHello = "Hello, I'm " + name

    }

    val p = new Person("leo") {

      override def sayHello = "Hi, I'm " + name

    }

     

    def greeting(p: Person { def sayHello: String }) {

      println(p.sayHello)

    }

     

    ====trait 特征

    使用trait(特征)相当于java中interface+abstract class

     

    scala中可以将trait混入到对象中,就是将trait中定义的方法、字段添加到一个对象中,

    作用: 给一个对象添加一些额外的行为, 例子:

    trait Logger {

        def log(msg:String) = println(msg)

      }

     

      class UserService

     

      def main(args: Array[String]): Unit = {

        val service = new UserService with Logger

        service.log("混入的方法")

      } 

     

    trait 责任链(调用链)

     

    trait HandlerTrait {

      def handle(data: String) = println("处理数据...")

    }

     

    trait DataValidHanlderTrait extends HandlerTrait {

      override def handle(data: String): Unit = {

        println("验证数据...")

        super.handle(data)

      }

    }

     

    trait SignatureValidHandlerTrait extends HandlerTrait {

      override def handle(data: String): Unit = {

        println("校验签名...")

        super.handle(data)

      }

    }

     

    class PayService extends DataValidHanlderTrait with SignatureValidHandlerTrait {

      override def handle(data: String): Unit = {

        println("准备支付...")

        super.handle(data)

      }

    }

     

    val service = new PayService

    service.handle("支付参数")

     

     结果:

    准备支付...

    校验签名...

    验证数据...

    处理数据...

     

     

     

    在Scala中,trait也是有构造代码的,也就是trait中的,不包含在任何方法中的代码

    // 而继承了trait的类的构造机制如下:

     

    1、父类的构造函数执行;

    2、trait的构造代码执行,多个trait从左到右依次执行;

    3、构造trait时会先构造父trait,如果多个trait继承同一个父trait,则父trait只会构造一次;

    4、所有trait构造完毕之后,子类的构造函数执行

     

      class Person { println("Person's constructor!") }

      trait Logger { println("Logger's constructor!") }

      trait MyLogger extends Logger { println("MyLogger's constructor!") }

      trait TimeLogger extends Logger { println("TimeLogger's constructor!") }

      class Student extends Person with TimeLogger with MyLogger {

        println("Student's constructor!")

      }

     

    //  Person's constructor!

    //    Logger's constructor!

    //    TimeLogger's constructor!

    //    MyLogger's constructor!

    //    Student's constructor!

     

     

    =======方法, 函数:

    方法是一个以def开头的带有参数列表(可以无参数列表)的一个逻辑操作块,这正如object或者class中的成员方法一样。

    函数是一个赋值给一个变量(或者常量)的匿名方法(带或者不带参数列表),并且通过=>转换符号跟上逻辑代码块的一个表达式。=>转换符号后面的逻辑代码块的写法与method的body部分相同。

    Scala 中的函数则是一个完整的对象,Scala 中的函数其实就是继承了 Trait 的类的对象。

     

    使用 val 语句可以定义函数,

    使用def 语句定义方法。

     

    ==> SAM 转换, 简单来说就是把只有一个方法的接口转换为匿名方法

      

    ==> implicit  隐式转换

     

    implicit conversion function

     

    主要功能: 1. 隐式类型转换, 2,隐式方法(对象)导入

     

    隐式转换的发生时机:

    隐式类似转化包括: 函数/方法参数类型不匹配时,自动转化参数

    隐式方法导入包括: 使用对象的方法不存在时,转换当前对象类型

     

    隐式作用域/查找范围:

    1.从当前作用域中查找val,var定义的对象

    2.从当前类的伴生对象中查找隐式转换

    3.从导入的包中查找隐式转化.

     

    Scala默认会使用两种隐式转换,一种是源类型,或者目标类型的伴生对象内的隐式转换函数;一种是当前程序作用域内的可以用唯一标识符表示的隐式转换函数

    隐式转换

    // 1、调用某个函数,但是给函数传入的参数的类型,与函数定义的接收参数类型不匹配(案例:特殊售票窗口)

    // 2、使用某个类型的对象,调用某个方法,而这个方法并不存在于该类型时(案例:超人变身)

    // 3、使用某个类型的对象,调用某个方法,虽然该类型有这个方法,但是给方法传入的参数类型,与方法定义的接收参数的类型不匹配(案例:特殊售票窗口加强版)

     

     

    ==> List

     

    head::tail  所以"::"的意思是head+tail组成一个新的 List , 注意 tail::head 是错误的, 因为head是一个值

     

    Set 默认是无需的, 子类包括 LinkedHashSet, SortedSet

     

     

    ===>Actor

     

    Scala的Actor类似于Java中的多线程编程。但是不同的是,Scala的Actor提供的模型与多线程有所不同。Scala的Actor尽可能地避免锁和共享状态,从而避免多线程并发时出现资源争用的情况,进而提升多线程编程的性能。此外,Scala Actor的这种模型还可以避免死锁等一系列传统多线程编程的问题。

     


     

     

    元组的索引从1开始,是因为对于拥有静态类型元组的其他语言,如Haskell和ML,从1开始是传统的设定。

     

    可变参数: echo(arr: _*)

    这个标注告诉编译器把 arr 的每个元素当作参数,而不是当作单一的参数传给 echo 。

     

    SBT:

    什么是SBT? SBT = (not so) Simple Build Tool,是scala的构建工具,与java的maven地位相同。其设计宗旨是让简单的项目可以简单的配置,而复杂的项目可以复杂的配置。

     

    ?SCALA 标识符

    字母数字标识符、操作符标识符、混合标识符、字面量标识符

     

    —可变集合

    var mutableArray = new ArrrayBuffer[int]()

    —不可变集合

    var arr= new Array[t](5);

     

    可变 list

     

    val li = ListBuffer[String]()

     

     

    set不可改变

    var s1 = Setr(1,2,3,4)

     

    hashset可变集合

     

    var s  = new Mutable.HashSet[int]()

     

    scala  转为 Java

    kafkaParams.asJava

     

     

     

    object 单例对象

     

    val 不可变变量, 使用_占位符

     

     

     

    Scala使用Actor作为其并发模型,Actor是类似线程的实体,通过邮箱发收消息。Actor可以复用线程,因此可以在程序中可以使用数百万个Actor,而线程只能创建数千个。在2.10之后的版本中,使用Akka作为其默认Actor实现。

     

    类和对象

     

    Scala中的类不声明为public,一个Scala源文件中可以有多个类。

     

    class :修饰的称为伴生类;定义在class中的属性都是动态的,用于实例化 的;scala中的class类默认可以传参数,默认的传参数就是默认的构造函数。class 类属性自带getter ,setter方法。使用class时要new (必须new,除非在对象伴生用apply方法【在加载类的时候默认自动调用】已实经例化好),并且new的时候,class中除了方法不执行,其他都执行。

     

    object: 修饰的称为伴生对象;定义在object中的属性(字段、方法)都是静 态的,main函数写在里面;scala 中的object是单例对象,相当于java中的工具类,可以看成是定义静态的方法的类.object不可以传参数。使用object时,不用new.

     

    Apply方法

           使用此方法时,可以在main函数中不通过new来创建一个对象,即可以不用专门的一次一次地进行实例化,加载创建对象的这个类的时候,会自动调用apply这个方法,类似Java中的static静态块

     

    在 Scala 中,是没有 static 这个东西的,但是它也为我们提供了单例模式的实现方法,那就是使用关键字 object。

    Scala 中使用单例模式时,除了定义的类之外,还要定义一个同名的 object 对象,它和类的区别是,object对象不能带参数。

    当单例对象与某个类共享同一个名称时,他被称作是这个类的伴生对象:companion object。你必须在同一个源文件里定义类和它的伴生对象。类被称为是这个单例对象的伴生类:companion class。类和它的伴生对象可以互相访问其私有成员。

     

     

     

    函数如果没有参数可以不传,, 不写括号

     

    在 Scala 中,字符串的类型实际上是 Java String,它本身没有 String 类。

     

     

    case class

    使用了case关键字的类定义就是样例类(case classes),样例类是种特殊的类。实现了类构造参数的getter方法(构造参数默认被声明为val),当构造参数是声明为var类型的,它将帮你实现setter和getter方法。

           样例类默认帮你实现了toString,equals,copy和hashCode等方法。

           样例类可以new, 也可以不用new

    如:

    case class Student(id: Int, age: Int)

     

    var s1= Student(1,1)

    var s2=Student(2,22)

    println(s2)

    ————

     

    Actor

    Actor Model是用来编写并行计算或分布式系统的高层次抽象(类似java中的Thread)让程序员不必为多线程模式下共享锁而烦恼,被用在Erlang 语言上, 高可用性99.9999999 % 一年只有31ms 宕机Actors将状态和行为封装在一个轻量的进程/线程中,但是不和其他Actors分享状态,每个Actors有自己的世界观,当需要和其他Actors交互时,通过发送事件和消息,发送是异步的,非堵塞的(fire-andforget),发送消息后不必等另外Actors回复,也不必暂停,每个Actors有自己的消息队列,进来的消息按先来后到排列,这就有很好的并发策略和可伸缩性,可以建立性能很好的事件驱动系统。

     

    Actor的特征:

    1.ActorModel是消息传递模型,基本特征就是消息传递

    2.消息发送是异步的,非阻塞的

    3.消息一旦发送成功,不能修改,类似于邮件的发送来往

    4.Actor之间传递时,自己决定决定去检查消息,而不是一直等待,是异步非阻塞的

     

     

     

     

  • 相关阅读:
    LeetCode 42. Trapping Rain Water
    LeetCode 209. Minimum Size Subarray Sum
    LeetCode 50. Pow(x, n)
    LeetCode 80. Remove Duplicates from Sorted Array II
    Window10 激活
    Premiere 关键帧缩放
    AE 「酷酷的藤」特效字幕制作方法
    51Talk第一天 培训系列1
    Premiere 视频转场
    Premiere 暴徒生活Thug Life
  • 原文地址:https://www.cnblogs.com/snow-man/p/13404175.html
Copyright © 2011-2022 走看看