scala

script
-------------
    文本文件存放源代码,不需要编译,解释执行。
    javascript
    shell
    python

scala
-------------
    java语句脚本化。 
    2.11

sql
javascript
python
vbscript
shell

安装scala
-------------
    1.下载scala-2.11.8.msi
    2.安装
        C:\myprograms\scala.2.11

    3.自动配置环境变量
        
    4.启动scala
        bin\scala.bat
        scala>

REPL
--------------
    read -> evaluate -> print -> loop

    类型推断

scala基本语法
----------------
    val    x = 10                        //常量,类型推断得到
    var    x = 10                        //变量

    1 + 1                            //操作符
    1.+(1)                            //操作符重载

    1 to 10                            //构造 1 ,2,3,4 .. 10序列
    "hello ".toUpperCase()            //字符串方法
    val x:Int = 10                    //声明类型

    [scala常用类型]
    java                scala
    --------------------------
    byte                Byte
    short                Short
    int                    Int                
    long                Long
    char                Char
    float                Float
    double                Double

    val x:BigInt = 123456789        //
    x * x * x * x * x * x * x * x    //大数运算

    //函数:直接调用的
    import scala.math._                //import math._
    sqrt(2)                            //开方函数
    pow(3,2)                        //幂函数

    //方法:通过对象调用的是方法。

    "hello world"(0)                //"hello".apply(4)
    BigInt("12345")                    //BigInt.apply(123)

scala控制语句
-----------------
    scala任何代码块都有返回值,最后一条语句就是返回值。
    val y = if(x > 0) 1 else -1
    //scala没有三元运算符
    val y = x > 0 ? 1 : -1            //wrong

    //Unit类型,表示()
    val:Unit = ()

    //scala没有switch语句。

    //{}的用法
    val y = if (x > 0) 1 else {
        -1
        }

    //粘贴模式
    :paste
    ...
    ctrl +d                    //结束


    //
    var x =100 ; x  =1000    //使用;表示终止

    //打印输出
    print("hello")
    println("hello")
    printf("%s=%d\r\n" , "tom" ,12)


    //读取控制台输入
    readLine("your name is : ")
    
    //while循环,scala没有i ++
    var n = 0 ;
    while(n < 10){
        n = n + 1
        println(n)    
    }

    
    //for循环
    for(x <- 1 to 10) println(x)

    var sum = 0 
    for(x <- 1 to 10) sum += x

    //until[1,10)
    val x = 1 until 10

    //while循环打印99表格
var row = 1 ;
while(row <= 9){
var col = 1 ;
while(col <=row){
printf("%dx%d=%d\t" , col , row , col * row)
col += 1
}
println()
row += 1
}

    //for循环打印99表格
    for(x <- 1 to 9){
        for(y <- 1 to x){
            printf("%dx%d=%d\t" , y , x , x * y)
        }
        println()
    }

    //scala没有break和continue
    import util.control.Breaks._
    for(x <- 1 to 10){println(x) ; break()}

    //for高级推导式,类似于双循环嵌套,
    for(x <- 1 to 3 ; y <- 4 to 6)println(x * y)

    //守卫条件
    for(x <- 1 to 5 ; y <- 4 to 6 if x == y)println(x * y)

    //yield产生新集合
    for(x <- 1 to 10 ) yield x * 2

    //函数
    def add(x:Int , y:Int):Int = x + y
    add(1,2)                                                //调用函数

    //递归函数必须声明返回值类型
    def fac(n:Int):Int = if(n == 1) 1 else n * fac(n-1)        //递归函数

    //默认参数和带名参数
    def decorate(pre:String = "<<<",str:String,suf:String=">>>") = pre+str+suf
    decorate("<<<","hello",">>>")
    decorate(str="hello" , pre="<<<",suf=">>>")                //

    //变长参数

    def sum(args:Int*) = {
        var sum =0  
        for(x <- args) sum += x 
        sum
    }

    sum(1 to 10:_*)        
    
    //过程,函数中没有=,返回值Unit, 表示()
    def out(){println("hello world")}
    out                                                    //ok,调用
    out()                                                //ok

    //lazy,延迟计算。
    var x = 1    + 1
    lazy val x = 1    + 1                                    //<lazy>



scala中"_"用法
----------------
    1.导包
        import math._                //统配

    2.1 to 10转序列
        1 to 10:_*            


作业
------------
    scala实现百钱买白鸡问题!
    100块钱买100只鸡.
    公鸡: 5元/只
    母鸡: 3元/只
    小鸡: 1元/3只
var x = 0
var y = 0     //三层for循环
var z = 0
for(x <- 0 to  20){
for(y<- 0 to 33){
for(z<- 0 to (100-x-y)){
if(z%3==0){
if(x*5+y*3+z/3==100){
if(x+z+y==100){
println("公鸡:"+x+"母鸡:"+y+"小鸡:"+z)
}
} 
}
}
}
}

for(x<- 0 to 20 ; y<- 0 to 30 ; z<- 0 to (100-x-y) if(z%3==0) if(x+z+y==100) if(x*5+y*3+z/3==100))println("公鸡:"+x+"母鸡:"+y+"小鸡:"+z)




//************************************************8

scala
------------
    java脚本化。
    函数式编程。
    开发效率高
    procedure        //def xx(){}
    function        //def xxx() = {}
    类型推断
    val                //常量
    var                //变量

while(){
}

for(x <- 1 to 10 if ..){
    println(x) ;
}

数组
---------------
    //创建数组,长度10,Int是泛型。
    val arr = new Array[Int](10)

    //快速构建数组
    val arr = Array(1,2,3)
    val arr = Array.apply(1,2,3)

    val arr = new Array[Int](3)
    //访问特定元素,下标值
    arr(0) = 1
    arr(1) = 2
    arr(2) = 3

    //
    val arr = Array[Int](3)
    val arr = new Array[Int](3)

变长数组(缓冲区)
--------------
    import scala.collection.mutable.ArrayBuffer
    val buf = ArrayBuffer(1,2,3)
    val buf = ArrayBuffer[Int]()

    //=对自身的内容进行改变
    buf.+=(1,2,3)

    //++不改变自身,生成新对象,操纵集合
    buf.++(1 to 10)

    //++/--通常是操纵集合元素

    //移除最后的n个元素,修改自身
    buf.trimEnd(3)

    //insert,在指定索引位置插入元素
    buf.insert(n:Int , seq:Int*)
    buf.insert(0,1)
    buf.insert(0,2,3,4)

    //从指定位置开始移除多少元素
    buf.remove(0,2)                        //移除开始的两个元素
    buf.remove(0)                        //移除第一个元素

    
    //遍历数组
    for(x <- buf) println(x)

    for(i <- 0 until buf.size) println(buf(0))

    //反转元素位置,10 ...1
    val x = (1 to 10).reverse

    
    //yield生成新集合
    for(x <- buf) yield x / 2

    //常用函数
    buf.sum
    buf.max
    buf.min

    //快速排序数组
    val a = buf.toArray
    scala.util.Sorting.quickSort(a)

    //数组转换String
    buf.mkString(",")
    buf.mkString("[",",","]")            //修饰符,前缀,后缀,连接符。

多维数组
-----------
    val arr = Array[Int]()
    val arr = Array[Array[Int]]()

    val arr = Array[Array[Int]](Array(1),Array(1,2),Array(1,2,3))

    for(x <- arr){
        for(y <- x){
            print(y)
        }
        println()
    }

    //构造多维数组
    val ma = Array.ofDim[Int](3,4)        //
    ma(0)(1) = 5                        //访问数组元素


和java集合的互操作
---------------------
    //自动将java的list转换成scala buffer
    def f1(list:java.util.List[String]) = println(list.size())
    val alist = new java.util.ArrayList[String]()
    alist.add("tom1")
    alist.add("tom2")
    alist.add("tom3")
    f1(alist)                //3

    f1(buf)                    //wrong

    //自动把Scala的buffer转换成java的list
    def f2(buf:Buffer[String])= println(buf.size)
    import scala.collection.JavaConversions.bufferAsJavaList
    f1(buf)                    //ok


映射和元组
----------------------
    1.映射
        Map,是对偶的集合。
        val m = Map(1->"tom",2->"tomas")
        val m = Map((1 , "tom"),(2,"tomas"),(3,"tomasLee"))
        m(1)                //m.apply(1)
        m(1) = "jerry"        //可以修改

        for((k,v) <- m) println(k + "==>" + v)        //迭代元组

    2.元组
        n个信息的组成,等价一个记录。
        类型可以不同。
        val t = (1,"tom",12) ;
        val t = new Tuple3[Int,String,Int](1,"tom",12)
        t._1
        t._2
        t._3                //元组内容不能修改。

    3.对偶
        特殊的元组,只有两个元素。
        val couple = (1,"tom")
        val couple = 1 -> "tom"
        val couple:Tuple2[Int,String] = 1 -> "tom"

    4.map和java Map互操作
        import scala.collection.JavaConversions.mapAsJavaMap
        import scala.collection.JavaConversions.propertiesAsScalaMap
    
    5.拉链操作
        将两个数组的元素一一组合,形成对偶的集合
        val ids = Array(1,2,3)
        val names = Array("tom1", "tom2" ,"tom3")
        ids.zip(names)

        //如果两边元素个数不同,-1:左侧集合的占位,nobody是右侧集合的占位。
        ids.zipAll(names,-1,"nobody")

        //zipWithIndex 元素和自己的索引构成couple
        names.zipWithIndex()

scala类
--------------
    //定义类
    class Dog{
        private var age:Int = 0 
        def incre() = age += 1
        def old() = age 
    }

    //实例化对象
    val d = new Dog
    d.<tab>

    class Dog{
        var age:Int = 0 ;
        def incre() = {age += 1};
        def old() = {age} ;
    }

    val d = new Dog()
    //get
    d.age
    //set
    d.age = 11

scala字段生成方法的原则:
-------------------------
    1.字段private,get/set也是私有的
    2.字段是val,只有get
    3.如果不需要任何get/set,可以定位private[this]


scala的private[this]
-------------------------
    只能在自己的对象中访问。
    class Dog{
    private[this] var age:Int = 0 ;
    def setAge(n:Int) = {this.age = n} ;
    def getAge() = this.age ;

    //实现标注的get/set方法
    @scala.beans.BeanProperty
    var coler:String = "yellow"
    
    //错误的,因为age是private[this]
    def compare(d:Dog)={
      this.age > d.age            
    }
    }

辅助构造器
-----------------------
    //主构造(name:String,age:Int)
    class Dog(name:String,age:Int,color:String , owner:String){
        //辅助构造
        def this()={
            this("yellow" , 12)

        }

        def who() = owner ;
    }

    1.var生成get、set方法
    2.val只对应get方法
    3.缺失var和val,如果不参与计算,不会生成任何成员
    4.缺失var和val,如果参与计算,升格为字段.


对象(单例对象)
-----------------------
    scala没有静态之说,通过object进行实现。
    object中定义的成员都是静态的。

    //内部使用java的单例设计模式实现
    Object Benz{
        val brand:String= "BENZ"
    }
    //访问静态成员
    Benz.brand

伴生对象
----------------------
    和类同名的对象就是类的伴生对象。
    class Benz{
      var color : String = "black"
    }

    object benz{
      val brand:String = "BENZ" 
    }

编写能执行scala程序
--------------------
    //编写scala入口类
    [app.scala]
    object App{
      def main(args:Array[String]) = {
        println("hello world")
      }
    }
    //编译
    scalac app.scala
    //执行
    scala app
    //直接执行scala源代码
    scala app.scala

idea安装scala插件
------------------
    1.下载scala-intellij-bin for 2016.3.6.zip
    2.settings ->plugins -> install plugin from disk ... ->定位到zip文件 ->install
    3.重启idea即可.
    4.验证


trait
-------------------
    等价于java的接口。
    scala对应第一个接口使用extends关键在,其他接口使用with
    trait USB1{
        def slot1() ;
    }

    trait USB2{
        def slot2() ;
    }

    trait USB3{
        def slot3() ;
    }


    class Mp3 extends USB1 with USB2 with USB3{
        override def slot(): Unit = {
            printf("~~~")
        }

        override def slot2(): Unit = {

        }

        override def slot3(): Unit = {
            
        }
    }

apply方法
-----------------
    apply方法定义在object中,为了快速构造对象.
    /**
      * Created by Administrator on 2018/2/9.
      */
    class Dog(var name:String,var age :Int) {

    }

    object Dog{
        def apply(n:String,age:Int) = new Dog(n,age)
    }


    val d = new Dog("tom",12)
    val d = Dog("tom",12)
    val d = Dog.apply("tom",12)


scala包和导入
--------------------
    1.定义包
        //嵌套定义
        package com{
            packate xxxx ;
        }

        //串联定义
        package com.xxx.
    
    2.别名
        import java.util.{List => juList}
        val l:juList[String ] = new java.util.ArrayList[String]()


构造父类对象
--------------------
    //主构造
    class Dog(var name:String,var age :Int) {
    }

    //继承,
    class Jing8(var n:String , var a:Int , var color:String) extends Dog(n,a){

    }

    //抽象类
    abstract class Aniaml{
        //抽象方法
        def cry() ;
        //抽象字段
        var age:Int

    }

scala类层级关系
---------------------
    Any
     ^
     |
     ---class AnyVal
     |            ^
     |            |---- Byte
     |            |---- Int
     |            |---- Short
     |            |---- ...
     |            |---- Unit
     |
     |
     ---class AnyRef
                ^         
                |---- Java Class
                |---- Scala class 
     
     ---class Nothing
     ---class Null


Null和null
-------------------------------------
    Null是类型,null是该类型唯一的一个值.
    null不可以给anyValue类型变量赋值,可以给
    AnyRef赋值。

    val x : Null = null ;

Nothing
-------------------------------------
    是类型,并且没有实例。常用于集合的泛型。
    case object Nil extends List[Nothing]
    Nil表示空集合。
    Nothing可以理解为任何类型的子类型。
    val x :List[Int] = Nil
    val x :List[String] = Nil

Unit
------------------------------------
    java中方法没有返回值的使用void类型。
    scala中的unit相当于java的void.
    Unit只有一个值,()
    val x:Unit = ();



文件与正则
--------------
    //读取文件
    val it = scala.io.Source.fromFile("d:/java/1.txt").getLines()
    for(x <- it){
        println(x)
    }

    //二进制读取
    val f:java.io.File = new File("d:\\java\\1.txt")
    val fis = new FileInputStream(f)
    val baos = new ByteArrayOutputStream()
    val buf = new Array[Byte](f.length().toInt)
    fis.read(buf)
    fis.close()
    println(new String(buf))

    //?????缓冲流读取?????

进程控制
--------------
    import sys.process._
    //!返回的命令对执行结果,0或其他值。
    val x:Int = ("dir d:/" !)

    //!!返回字符串,x是执行的结果字符串
    val x = ("dir d:/" !!)


特质
--------------
    class RichInt extends OrderedProxy..

    1.自身类型
        限制自己可供哪些类使用。
        /**
          * Created by Administrator on 2018/2/9.
          */
        class Vip extends VipRoom{
            override def tea(): Unit = {

            }
        }

        //错误,不符合特质自身类型
        class Customer extends VipRoom{
            override def tea(): Unit = {

            }
        }

        //vip房间
        trait VipRoom {
            //只能Vip能实现该特质。
            this:Vip=>
            def tea()
        }

操作符
---------------
    1.中置操作符
        放在两个操作数的中间。
        调用的对象的方法有一个参数。
        可以使用中置操作符
        1 to 10
        1.to(10)

        class Dog = {
            def compare(d:Dog) = -1
        }

        val d1 = new Dog()
        val d2 = new Dog()
        d1.compare(d2)
        d1 compare d2

    2.一元操作符
        //前置操作符
        +        //+号
        -        //-号
        !        //boolean取反
        ~        //按位取反
        
        //将前置操作符转换成方法
        0.unary_~
        0.unary_+
        0.unary_-
        ttue.unary_!

        //赋值操作符
        var a = 0 
        a +=
        a -=
        a *=
        a /=
        var x = 0
        x -= 1
        x *= 1
        x /= 1
        x %= 1


    3.结合性
        :结尾的都是右操作符。
        val a = Array(1,2,3)

        //4,1,2,3
        a.+:(4)            //方法调用
        4 +: a            //右操作符

        val a = Array(1,2,3)
        val b = Array(4,5,6)
        a ++: b            //1,2,3,4,5,6

        1 :: 2 :: 3 :: Nil            //1,2,3
        Nil.::(3).::(2).::(1)        //1,2,3

update和apply
-------------------
    val m = mutable.HashMap[String,Int]("tom1"->100 , "tom2"->80)
    //apply
    m("tom1")
    m.apply("tom1")

    //更新
    m("tom2") = 300
    m

    //定义分数类和*方法
    class Fraction(var top:Int,var bot:Int) {
        def *(f:Fraction) = {
            Fraction(top * f.top , bot * f.bot)
        }

    }

    object Fraction{
        def apply(a:Int,b:Int) = new Fraction(a,b)
    }
    //apply
    val f1 = Fraction(1,2)
    val f2 = Fraction(1,3)
    //
    val f3 = f1 * f2
    val f4 = f1.*(f2)

提取器:unapply
------------------
    和apply相反,反解析对象,抽泣属性值的。
    class Fraction(var top:Int,var bot:Int) {
        def *(f:Fraction) = {
            Fraction(top * f.top , bot * f.bot)
        }

    }

    object Fraction{
        def apply(a:Int,b:Int) = new Fraction(a,b)

        def unapply(arg: Fraction): Option[(Int, Int)] = {
            if(arg.top == 0) None else Some(arg.top,arg.bot)
        }
    }

    object demo1{
        def main(args: Array[String]): Unit = {
            val f1 = Fraction(1,2)
            val f2 = Fraction(1,3)
            val f3 = f1 * f2
            //将f3的分子分母抽取出来,赋值给a1,b1
            val Fraction(a1,b1) = f3
        }
    }

_用法
-----------------
    import math._            //导包
    1 to 10 :_*                //转序列
    (1,2)._1                //元组访问
    val f = ceil _            //函数本身


高阶函数
----------------
    函数中的参数或者返回值也是函数。
    import scala.math._
    val x = 3.14
    ceil(x)                //4.0
    val f = ceil _        //
    f(x)
    
    //
    Array(1.1,2.2,3.3).map(f)

    //匿名函数
    (a:Int,b:Int)=>a + b
    val f = (a:Int,b:Int)=>a + b
    f(1,2)                            //调用函数

    //定义高阶函数
    def op(f:(Int,Int)=>Int,a:Int,b:Int) = f(a,b)
    def add(a:Int,b:Int) = a + b
    val f = add _
    op(f,1,2)
    op(add _ , 1,2)
    op(add, 1,2)
    op((a:Int,b:Int)=> a + b, 1,2)


    //1.高阶函数,返回值是函数
    def f0() = {
        def add(a:Int,b:Int) = a + b
        add _
    }
    f0()(1,2)

    //2.高阶函数,返回值是函数
    def f0() = { (a:Int,b:Int) => a + b }
    f0()(1,2)

    //3.
    def f0():(Int,Int)=>Int = { (a:Int,b:Int) => a + b }

    注意事项:
    函数声明:没有参数名称,只需要有类型即可。(Int,Int)=>Int
    匿名函数:有参数名称, (a:Int , b:Int) => a + b 
                         (a:Int , b:Int) =>{ a + b }:Int
    
    //函数示例
    val a = Array(1,2,3)            //1,2,3
    a.map((x:Int)=>x * 3)            //3,6,9
    a.map((x)=>x * 3)                //类型推断,省去了参数类型
    a.map(x=>x * 3)                    //省去了()
    a.map(_ * 3)                    //省去了()



柯里化
-----------------
    将多个参数转换成每次调用一个参数的函数,链条式调用即可。
    柯里化表示法,能够很好的利用类型推断和隐式值,调用简洁。
    
    //原函数
    add(x:Int,y:Int)= x + y

    //
    def add(x:Int)={
        def f(y:Int)=x+y
        f _
    }

    //柯里化,
    def add(x:Int)(y:Int)={
      x + y
    }
    def add(x:Int)(y:Int)(z:Int)={x + y + z}


控制抽象
------------------
//定义函数
def runInThread(block:()=>Unit) = {
new Thread(){
override def run(){
block()
}
}.start()
}

//调用函数
runInThread(()=>println("hello world"))

//使用换名调用表示法定义函数
def runInThread(block: =>Unit) = {
new Thread(){
override def run(){block}
}.start()
}

runInThread(println("hello world"))

List
----------------
    可重复。
    //不可变List
    val l = 1::2::3::Nil
    //
    l.++Array(4,5)


    //可变List
    import scala.collection.mutable.LinkedList
    val ll = LinkedList(1,2,3)
    val ll = LinkedList.apply(1,2,3)
    //赋值
    ll.elem = 0

    //错误,head不能赋值
    ll.head = 0 
    //
    ll.tail.elem = 0



Set
----------------
    不重复。
    val s = Set(1,2,3)
    s + 4
    s.head
    s.tail

    //循环
    s.foreach(println)

    val s1 = Set(1,2,3)
    val s2 = Set(2,3,4)
    
    //并集
    s1 | s2
    s1 union s2
    s1 ++ s2
    s1.++(s2)

    //交集
    s1 & s2
    s1.intersect(s2)

    //差集
    s1 &~ s2
    s1.diff(s2)
    s1 -- s2

    //函数应用给集合
    val l = List("tom","tomas" , "tomasLee")
    
    //转大写
    l.map(_.toUpperCase)
    //转大写
    for(x <- l) yield x.toUpperCase

化简和折叠
------------------
    //化简
    val l = List(1,2,3,4)

    //(1 + 2) + 3 + 4
    l.reduceLeft(_ + _) = 10
    l.reduceLeft(_ - _) = -8

    //1 - (2 - (3 - 4))
    l.reduceRight(_ - _) = -2


    //折叠(fold)
    l.foldLeft(0)(_ - _) = -10
    l./:(0)(_ - _) = -10
    l.foldLeft(10)(_ - _) = 0

    l.foldRight(0)(_ - _) = -2
    l.:\(0)(_-_) = -2
    
    0 :: l
    Array(-1,0).toList ::: l

    //通过迭代器迭代集合
    val it = l.iterator
    while(it.hasNext)println(it.next)

模式匹配
-----------------
//常规用法
val x = '+'
x match {
case '+' => println("+++++++")
case '-' => println("-------")
case _ => println("~~~~~~~")
}

//守卫条件
val x = '1'
x match {
case '+' => println(" > 0 ")
case '-' => println(" < 0 ")
case _ if Character.isDigit(x)=> println("is number")
case _ => println("other")
}

//跟随变量
val str = "123"
str.length() match {
case 10 => println(" long string ")
case 2 => println(" short string ")
case len => println("normal string , str's length is " + len)
}

//常量控制
import  java.awt.Color._
val c = "bluegreen"
val bluegreen = "bluegreen"
c match{
  //case RED => println("red color!!") 
  //识别成常量,否则就是变量对待
  case `bluegreen` => println("red BLUEGREEN!!") 
}

//类型判断
val x:Any = "hello"
x match{
  case a:Int => println("整数")
  case b:String => println("字符")
  case c => println("其他")
}

//匹配数组,列表,元组
val arr = Array(2,"3")
arr match{
  case Array(0) => println(1)
  case Array(x,y) => println("2" + x + "," + y)
  case Array(0,_*) => println(3)
  case _ => println(4)
}

val l = 0 :: 1 ::2 :: Nil
l match{
  //0
  case 0::Nil => println(1)
  //2元素
  case x::y::Nil => println(2)
  //以0开头
  case 0::tail => println(3)
  case _ => println(4)
}

//元组
val t:Tuple2[Any,Any] = ("1","2")
t match{
  case (1,_) => println(1)
  case (y,2) => println(2)
  case _ => println(3)
}

//提取器(unapply)
val t = ("001","tomas")
val (id,name) = t

val (a,b) = BigInt(5) /% 2

系统属性
------------
//自动转换properties集合成scala的map
import scala.collection.JavaConversions._
val prop = System.getProperties
for((k,v) <- prop){
    println(k + "-->" + v)
}

样例类
--------------
    优化之后的类,方便用于模式匹配。
    内置实现hashcode,toString,serializable接口,可比较接口。
    apply()/unapply()

    abstract class Amount
    case class Dollar(v:Double) extends Amount
    case class Currency(v:Double, unit:String) extends Amount
    case object Nothing00 extends Amount

    var a: Amount= Dollar(100)
    a = Currency(100,"人民币")
    a = Nothing00
    a match{
        case Dollar(v) => println("美元 : " + v)
        case Currency(u,v) => println("货币 : " + u + " , " + v)
        case Nothing00 => println("nonnn")
    }

密封类
---------------
    sealed修饰的类,密封的所有子类必须和自己位于同一个源文件中。
    能够在一个文件中找到所有的子类。

    sealed abstract class Amount
    case class Dollar(v:Double) extends Amount
    case class Currency(v:Double, unit:String) extends Amount
    case object Nothing00 extends Amount

Option
---------------
    可空。
    sealed abstract class Option
    //有值
    case class Some[+A](x: A) extends Option
    //等价于null
    case object None extends Option[Nothing]

    //使用Option定义函数返回值,有效规避null判断问题,
    //使用None样例对象为特定空值。
    def getScore(name:String):Option[Double] = {
        if(name.equals("tom")){
            None
        }else{
            Some(100)
        }
    }

    val s = getScore("tom")
    if(s.isEmpty){
        println("没有此用户")
    }
    else{
        println("分数 : " + s.get)
    }

偏函数
-----------------
    包含在{}内的一组case语句。
    对模式匹配中的匹配条件进行重用。
    本质上就是模式匹配,能够进行重用。
    val f:PartialFunction[Char,Int]= {case '+' => 1 ; case '-' => -1 ; case _ => 0}
    //调用偏函数
    println(f('0'))
    //判断是否定义了特定字符的处理方式。
    f.isDefinedAt('+')

类型参数
------------------
    //类泛型
    class Pair[T,S](val one:T,val two:S)

    val o1 = new Pair(100,"tom")
    //right
    val o2 = new Pair[Int,String](100,"tom")
    
    //wrong
    val o2 = new Pair[String,String](100,"tom")
    
    //方法泛型
    def middle[T](arr:Array[T]) = arr(arr.length / 2)
    middle(Array(1,2,3))

    //泛型边界,T必须是Comparable子类或实现类。
    // <: 上限
    class Pair[T <: Comparable[T]]{
        def smaller(a:T , b:T) = {
            if(a.compareTo(b) < 0) a else b
        }
    }

    val o = new Pair[java.lang.Integer]()
    println(o.smaller(1,2))

    // >: 下限 ,不好使!!
    class Pair[T](val first:T , val second:T){
        def replaceFirst[R >: T](a:R) = new Pair[R](a,second)
    }

    class Dog
    class Jing8(name:String) extends Dog
    class VipJing8(val name:String,val age:Int) extends Jing8(name)

    val j1 = new Jing8("j1")
    val j2 = new Jing8("j2")
    val j3 = new VipJing8("j3",12)

    val p1 = new Pair[Jing8](j1,j2)
    val d1 = new Dog()
    val p2 = p1.replaceFirst(j3)
    println(p2.first)
    println(p2.second)

    // <% : 视图界定,能够隐式转换成需要的类型。
    class Pair[T <% Comparable[T]]{
        def smaller(a:T , b:T) = {
            if(a.compareTo(b) < 0) a else b
        }
    }

    val o = new Pair[Int]()
    println(o.smaller(1,2))

    //型变
    1.协变
        class Pair[+T]
        
        class Person
        class Student extends Person
        Pair[Student]是Pair[Person]的子类型

    2.逆变
        class Pair[-T]

        class Person
        class Student extends Person

        Pair[Student]是Pair[Person]的父类型


隐式转换
----------------
    1.隐式转换函数
        使用implicit修饰的带有单个参数的函数。
        val f1 = Fraction(1,2)
        //隐式转换函数
        implicit def fff(n:Int) = Fraction(n,1)
        val f2 = f1 * 3
        println(f2.top)

        //java转换包
        import scala.collection.JavaConversions._

    2.隐式参数
        //
        case class Decorator(val left:String , val right:String)
        //隐式参数
        def quote(what:String)(implicit dec:Decorator) = dec.left + what + dec.right
        //隐式值
        implicit val d = Decorator("{{{", "}}}")
        //
        println(quote("hello"))

scala实现单词统计
-----------------
    //加载文件
    val it = Source.fromFile("d:/1.txt").getLines()
    var list:List[String] = Nil

    for(line <- it){
        list = line :: list
    }
    //统计单词个数,压扁
    val list2 = list.flatMap(_.split(" "))
    val list3 = list2.groupBy((s:String)=>s)

    //def f1(a:Tuple2[String,List[String]]) = (a._1 , a._2.length)
    val list4 = list3.map((a:Tuple2[String,List[String]])=>(a._1,a._2.length))
    println()


    //排序,分组,转换list,
    val it = Source.fromFile("d:/1.txt")
    val doc = it.getLines().mkString(" ")
    val list = doc.split(" ").toList

    val list2 = list.groupBy((s:String)=>s).map((t:Tuple2[String,List[String]])=>(t._1,t._2.length))


    val list3 = list2.toList
    val list4 = list3.sortBy((t:Tuple2[String,Int]) => -t._2)

    println(doc)

猜你喜欢

转载自www.cnblogs.com/zyde/p/8999306.html