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之间传递时,自己决定决定去检查消息,而不是一直等待,是异步非阻塞的

     

     

     

     

  • 相关阅读:
    Java中的break和continue关键字使用总结
    Java Foreach语句使用总结
    Android的线程(Thread)和服务(Service)的区别
    Android终止无限循环线程和程序退出时销毁线程
    IoC(Inversion of Control,控制反转)模式
    浅谈手机app测试注意点
    Android获取手机相关信息
    深搜
    5种排序方式
    一个简单的文本编辑器
  • 原文地址:https://www.cnblogs.com/snow-man/p/13404175.html
Copyright © 2011-2022 走看看