scala编程语言课堂笔记

1、scala编程语言

2、Spark Core : Spark内核 ,最重要的一个部分。

3、Spark SQL : 类似于 hive  和 pig。数据分析引擎。sql语句提交到spark集群中运行。

4、Spark Streaming :类似于 storm,用于流式计算、实时计算。本质:一个离线计算。

------------------------------Scala编程语言-------------------------------------------

---------------Scala基础--------------------------

一、scala简介

    1、scala是一个多范式的编程语言(支持多种方式的编程)

        (1)使用面向对象编程:封装、继承、多态

        (2)使用函数式编程:最大的特定

            (*)优点:代码非常简洁

            (*)缺点:可读性太差,尤其是隐式类、隐式函数、隐式参数         

    2、安装和配置scala

        (*)基于JDK,先安装JDK

        (*)scala:2.11.8(spark 2.1.0)

            (*)配置环境变量:SCALA_HOME

            (*)%SCALA_HOME%\bin 配置到path中             

        下载地址:https://www.scala-lang.org

        文档地址:https://www.scala-lang.org/api/2.11.8/#scala.math.package

         

        (*)开发环境

            (1)REPL命令行

            (2)IDEA : 需要安装scala插件。

             

二、Scala中的数据类型和变量常量

     

    1、注意一点:scala中所有的数据,都是对象。

        举例:1 java int 。在scala中,1 就是一个对象。

         

    2、基本数据类型

        Byte    8位有符号数字

        Short   16位有符号数字

        Int ...

        Long

        Float

        Double

         

        字符串类型

        String

        字符

        Char

         

        scala中字符串的插值操作:就是相当于字符串的拼接

        scala> var s1 : String = "Hello "

        s1: String = "Hello "

        scala> "My name is Tom and ${s1}"

        res1: String = My name is Tom and ${s1}

        插值操作时,需要加入 s

        scala> s"My name is Tom and ${s1}"

        res2: String = "My name is Tom and Hello "

         

    3、变量var和常量val

     

    scala> val s2 :String = "Hello all"

    s2: String = Hello all

    scala> s2 = "Hello everyone"

    <console>:12: error: reassignment to val

           s2 = "Hello everyone"

            

    4、Unit类型和Nothing类型

         

        (1)Unit类型,就是java中的void,没有返回值

         

            scala> val f = ()

            f: Unit = ()

             

            返回值 Unit类型

            () 代表了一个函数,这个函数没有返回值

             

        (2)Nothing类型,在执行过程中,产生了异常Exception

         

            举例:

            scala函数:scala中函数非常重要,是scala的头等公民

            用法很多:函数式编程、高阶函数

             

            def myFunction = 函数的实现

             

            scala> def myFun = throw new Exception("Some Error")

            myFun: Nothing

             

三、函数:头等公民

    (一)scala内置函数,可以直接使用的函数

     

        scala> max(1,2)

        <console>:12: error: not found: value max

               max(1,2)

               ^

        scala> import scala.math

           final package math

        scala> import scala.math._

        import scala.math._

        _ 就相当于java中的 * 代表包内所有东西

         

        scala> max(1,2)

        res4: Int = 2

         

        res4: Int = 2

        定义了一个变量 res4 ,接收了 max 函数的返回值。scala中支持类型的推导。

        res4 = ""

         

    (二) 自定义函数

        语法:

         

        def 函数名称([参数名称:参数类型]*) : 返回值类型 = {

            函数的实现

        }

         

        举例:

        1、求和

        scala> def sum(x:Int,y:Int):Int = x + y

        sum: (x: Int, y: Int)Int

        scala> sum(1,2)

        res5: Int = 3

         

        2、求阶乘,5!= 5 * 4* 3 *2* 1

        递归

        scala> def myFactor(x:Int):Int = {

             | if(x<=1)

             | 1

             | else

             | x*myFactor(x-1)

             | }

        myFactor: (x: Int)Int

        scala> myFactor(5)

        res6: Int = 120

         

        注意:没有return语句。

        函数的最后一句话,就是函数的返回值。

         

        3、求输入的年份是否是闰年

         

        闰年:

        普通闰年:可以被4整除但是不能被100整除的年份

        世纪闰年:可以被400整除的年份

         

        scala> def isLeapYear(x:Int) = {

             | if(( x%4 == 0 && x%100 != 0) || (x%400==0)) true

             | else false

             | }

        isLeapYear: (x: Int)Boolean

        scala> isLeapYear(2019)

        res7: Boolean = false

        scala> isLeapYear(2008)

        res8: Boolean = true

         

        1、( x%4 == 0 && x%100 != 0) || (x%400==0)

        2、函数定义的时候,可以不写返回值,因为scala支持类型推导

         

四、循环语句

    1、类似于java的用法 while dowhile for

    2、foreach循环(Spark算子)

     

    讲义在代码中

     

五、scala的函数参数

    1、函数参数的求值策略

        (1)call by value  :

         

            对函数的实参求值,并且只求一次

             

        (2)call by name  : =>

         

            函数实参在函数体内部用到的时候,才会被求值

             

            举例:

             

            scala> def test1(x:Int,y:Int) = x + x

            test1: (x: Int, y: Int)Int

            scala> test1(3+4,8)

            res9: Int = 14

            scala> def test2(x : => Int,y : => Int) = x+x

            test2: (x: => Int, y: => Int)Int

            scala> test2(3+4,8)

            res10: Int = 14

             

            执行过程对比:

            test1 ---> test1(3+4,8)  ---> test1(7,8)  ---> 7+7 ---> 14

            test2 ---> test2(3+4,8)  ---> (3+4) + (3+4)  ---> 14

             

        (3)复杂的例子

         

            def bar(x:Int,y : => Int) : Int = 1

            x 是 value y 是 name

             

            定义一个死循环:

            def loop() : Int = loop

             

            调用bar函数的时候:

            1、bar(1,loop)

            2、bar(loop,1)

             

            哪个方式会产生死循环?

             

            scala> def bar(x:Int,y : => Int) : Int = 1

            bar: (x: Int, y: => Int)Int

            scala> def loop() : Int = loop

            loop: ()Int

            scala> bar(1,loop)

            res11: Int = 1

            scala> bar(loop,1)

             

            解析:

            1、虽然 y 是 name, 每次调用的时候会被求值。但是,函数体内,没有调用到y.

            2、x 是 value,对函数参数求值,并且只求一次。虽然后面没有用到x,但求值时产生了死循环。

    2、scala中函数参数的类型

        (1)默认参数

            当你没有给参数值赋值的时候,就会使用默认值。

             

            def fun1(name:String="Tom") :String = "Hello " + name

             

             

            scala> def fun1(name:String="Tom") :String = "Hello " + name

            fun1: (name: String)String

            scala> fun1("Andy")

            res0: String = Hello Andy

            scala> fun1()

            res1: String = Hello Tom

             

             

        (2)代名参数

            当有多个默认参数的时候,通过代名参数可以确定给哪个函数参数赋值。

            def fun2(str:String = "Hello " , name:String = " Tom " ,age:Int = 20) = str + name + " age is " +age

         

         

            scala> def fun2(str:String = "Hello " , name:String = " Tom " ,age:Int = 20) = str + name + " age is " +age

            fun2: (str: String, name: String, age: Int)String

            scala> fun2()

            res2: String = Hello  Tom  age is 20

            scala> fun2("Andy")

            res3: String = Andy Tom  age is 20

            scala> fun2(name="Andy")

            res4: String = Hello Andy age is 20

             

        (3)可变参数

            类似于java中的可变参数,即 参数数量不固定。

            scala> def sum(args:Int*)= {

                 | var result = 0

                 | for(s<-args) result +=s

                 | result

                 | }

            sum: (args: Int*)Int

            scala> sum(1,2,3,4)

            res5: Int = 10

            scala> sum(1,2,3,4,3,4)

            res6: Int = 17

             

六、懒值(lazy)

    铺垫:Spark的核心是 RDD(数据集合),操作数据集合的数据,使用算子来操作RDD(函数、方法)

    算子:

    Transformation : 延时加载,不会触发计算

    Action : 会立刻触发计算。

     

    定义:常量如果是lazy的,他的初始化会被延迟,推迟到第一次使用该常量的时候。

     

    举例:

    scala> var x : Int = 10

    x: Int = 10

    scala> val y : Int = x+1

    y: Int = 11

     

    y 的值是x+1 定义后会立即进行计算

    scala> lazy val z : Int = x+1

    z: Int = <lazy>

    z的初始化会被延迟

    scala> z

    res0: Int = 11

    当我们第一次使用z的时候,才会触发计算

     

    读文件:

    scala> val words = scala.io.Source.fromFile("H:\\tmp_files\\student.txt").mkString

    words: String =

    1       Tom     12

    2       Mary    13

    3       Lily    15

    scala> lazy val words = scala.io.Source.fromFile("H:\\tmp_files\\student.txt").mkString

    words: String = <lazy>

    scala> words

    res1: String =

    1       Tom     12

    2       Mary    13

    3       Lily    15

    scala> lazy val words = scala.io.Source.fromFile("H:\\tmp_files\\student123123121.txt").mkString

    words: String = <lazy>

     

    定义成lazy后,初始化被延迟,所以不会抛异常

    scala> val words = scala.io.Source.fromFile("H:\\tmp_files\\student123123121.txt").mkString

    java.io.FileNotFoundException: H:\tmp_files\student123123121.txt (系统找不到指定的文件。)

      at java.io.FileInputStream.open0(Native Method)

      at java.io.FileInputStream.open(FileInputStream.java:195)

      at java.io.FileInputStream.<init>(FileInputStream.java:138)

      at scala.io.Source$.fromFile(Source.scala:91)

      at scala.io.Source$.fromFile(Source.scala:76)

      at scala.io.Source$.fromFile(Source.scala:54)

      ... 32 elided

     

七、例外:Exception 

    类似于java

    还是有一些变化

     

    文件操作:

    scala> val words = scala.io.Source.fromFile("H:\\tmp_files\\student.txt").mkString

    words: String =

    1       Tom     12

    2       Mary    13

    3       Lily    15

    scala> val words = scala.io.Source.fromFile("H:\\tmp_files\\student1231312312312.txt").mkString

    java.io.FileNotFoundException: H:\tmp_files\student1231312312312.txt (系统找不到指定的文件。)

      at java.io.FileInputStream.open0(Native Method)

      at java.io.FileInputStream.open(FileInputStream.java:195)

      at java.io.FileInputStream.<init>(FileInputStream.java:138)

      at scala.io.Source$.fromFile(Source.scala:91)

      at scala.io.Source$.fromFile(Source.scala:76)

      at scala.io.Source$.fromFile(Source.scala:54)

      ... 32 elided

       

    见代码

       

八、数组

    1、数组的类型

        (1)定长数组:Array

            scala> val a = new Array[Int](10)   ----->  (10) 就是数组的长度

            a: Array[Int] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)

            scala> val a = new Array[String](10)

            a: Array[String] = Array(null, null, null, null, null, null, null, null, null, null)

            初始化赋给默认值

             

            scala> val c : Array[String] = Array("Tom","Lily")

            c: Array[String] = Array(Tom, Lily)

            scala> val c : Array[String] = Array("Tom","Lily",1)

            <console>:11: error: type mismatch;

             found   : Int(1)

             required: String

                   val c : Array[String] = Array("Tom","Lily",1)

             

            不能往数组中添加不同类型的元素

             

             

        (2)变长数组:ArrayBuffer

         

            scala> val d = ArrayBuffer[Int]()

            <console>:11: error: not found: value ArrayBuffer

                   val d = ArrayBuffer[Int]()

                           ^

            scala> import scala.collection.mutable._

            import scala.collection.mutable._

            scala> val d = ArrayBuffer[Int]()

            d: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()

             

            scala> d += 1

            res2: d.type = ArrayBuffer(1)

            scala> d += 2

            res3: d.type = ArrayBuffer(1, 2)

            scala> d += (1,2,3,4)

            res4: d.type = ArrayBuffer(1, 2, 1, 2, 3, 4)

            scala> d.

            ++             combinations     groupBy              mapResult           reverse           to

            ++:            companion        grouped              max                 reverseIterator   toArray

            ++=            compose          hasDefiniteSize      maxBy               reverseMap        toBuffer

            ++=:           contains         hashCode             min                 runWith           toIndexedSeq

            +:             containsSlice    head                 minBy               sameElements      toIterable

            +=             copyToArray      headOption           mkString            scan              toIterator

            +=:            copyToBuffer     indexOf              nonEmpty            scanLeft          toList

            -              corresponds      indexOfSlice         orElse              scanRight         toMap

            --             count            indexWhere           padTo               segmentLength     toSeq

            --=            diff             indices              par                 seq               toSet

            -=             distinct         init                 partition           size              toStream

            /:             drop             inits                patch               sizeHint          toString

            :+             dropRight        insert               permutations        sizeHintBounded   toTraversable

            :\             dropWhile        insertAll            prefixLength        slice             toVector

            <<             endsWith         intersect            prepend             sliding           transform

            WithFilter     equals           isDefinedAt          prependAll          sortBy            transpose

            addString      exists           isEmpty              product             sortWith          trimEnd

            aggregate      filter           isTraversableAgain   readOnly            sorted            trimStart

            andThen        filterNot        iterator             reduce              span              union

            append         find             last                 reduceLeft          splitAt           unzip

            appendAll      flatMap          lastIndexOf          reduceLeftOption    startsWith        unzip3

            apply          flatten          lastIndexOfSlice     reduceOption        stringPrefix      update

            applyOrElse    fold             lastIndexWhere       reduceRight         sum               updated

            canEqual       foldLeft         lastOption           reduceRightOption   tail              view

            clear          foldRight        length               reduceToSize        tails             withFilter

            clone          forall           lengthCompare        remove              take              zip

            collect        foreach          lift                 repr                takeRight         zipAll

            collectFirst   genericBuilder   map                  result              takeWhile         zipWithIndex

             

            举例:去掉数组中,最后两个元素

            scala> d

            res5: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 1, 2, 3, 4)

            scala> d.trimEnd(2)

            scala> d

            res7: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 1, 2)

             

            遍历数组:

             

            for循环、foreach:

            scala> var a = Array("Tom","Lily","Andy")

            a: Array[String] = Array(Tom, Lily, Andy)

            scala> for(s <- a ) println(s)

            Tom

            Lily

            Andy

            scala> a.foreach(println)

            Tom

            Lily

            Andy

             

            数组的常见操作举例:

            scala> val myarray = Array(1,2,7,8,10,3,6)

            myarray: Array[Int] = Array(1, 2, 7, 8, 10, 3, 6)

            scala> myarray.max

            res10: Int = 10

            scala> myarray.min

            res11: Int = 1

            scala> myarray.sortWith(_>_)

            res12: Array[Int] = Array(10, 8, 7, 6, 3, 2, 1)

            scala> myarray.sortWith(_<_)

            res13: Array[Int] = Array(1, 2, 3, 6, 7, 8, 10)

             

            解释:(_>_)

            完整 : sortWith函数里面,参数也是一个函数  --> 高阶函数

             

            _>_   函数

             

            def comp(a:Int,b:Int) = {if(a>b) true else false}

             

            (a,b) => {if(a>b) true else false}

             

            (a,b) => {if(a>b) true else false}   ---->  _>_

             

            _>_ 是一个函数,传入两个参数,返回值是bool

    2、多维数组

        和java类似,通过数组的数组来实现

         

        scala> var matrix = Array.ofDim[Int](3,4)

        matrix: Array[Array[Int]] = Array(Array(0, 0, 0, 0), Array(0, 0, 0, 0), Array(0, 0, 0, 0))

     

            Array(0, 0, 0, 0)

            Array(0, 0, 0, 0)

            Array(0, 0, 0, 0)

         

        三行四列的数组

         

        scala> matrix(1)(2)=10

        scala> matrix

        res15: Array[Array[Int]] = Array(Array(0, 0, 0, 0), Array(0, 0, 10, 0), Array(0, 0, 0, 0))

         

        数组下标是从0开始的

         

        例子:

        定义一个二维数组,其中每个元素是一个一维数组,并且长度不固定

         

        scala> var triangle = new Array[Array[Int]](10)

        triangle: Array[Array[Int]] = Array(null, null, null, null, null, null, null, null, null, null)

         

        初始化:

        scala> for(i <- 0 until triangle.length){

             | triangle(i) = new Array[Int](i+1)

             | }

        scala>  triangle

        res17: Array[Array[Int]] = Array(Array(0), Array(0, 0), Array(0, 0, 0),

        Array(0, 0, 0, 0), Array(0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0, 0),

        Array(0, 0, 0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0, 0, 0, 0),

        Array(0, 0, 0, 0, 0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0))

         

        二维数组,如果使用 Array[Array[Int]](10) 声明时:

        1、首先指定的是外层数据的长度

        2、初始化内层数组的时候,再指定内层数组的长度

         

九、映射 <key,value> Map 

         

    举例:

        创建一个map,来保存学生的成绩

         

    scala> val scores = Map("Tom" -> 80,"Andy"->70,"Mike"->90)

    scores: scala.collection.mutable.Map[String,Int] = Map(Mike -> 90, Tom -> 80, Andy -> 70)

     

    1、Map[String,Int]  key String  value Int

    2、scala.collection.mutable

     

        scala中,映射是有两种,一种是可变map,一种是不可变map

        scala.collection.mutable  --->  可变

        scala.collection.immutable  --->  不可变

         

        scala> val scores2 = scala.collection.immutable.Map("Tom" -> 80,"Andy"->70,"Mike"->90)

        scores2: scala.collection.immutable.Map[String,Int] = Map(Tom -> 80, Andy -> 70, Mike -> 90)

         

    映射的初始化:

        scala> val scores2 = scala.collection.mutable.Map(("Tom",80),("Andy",70))

        scores2: scala.collection.mutable.Map[String,Int] = Map(Tom -> 80, Andy -> 70)

         

        scala> scores2=1

        <console>:15: error: reassignment to val

               scores2=1

                

    映射的操作:

         

        1、获取映射中的值

            scala> val chinese = scala.collection.mutable.Map(("Tom",80),("Andy",70))

            chinese: scala.collection.mutable.Map[String,Int] = Map(Tom -> 80, Andy -> 70)

            scala> chinese("Tom")

            res18: Int = 80

            scala> chinese.get("Andy")

            res19: Option[Int] = Some(70)

            scala> chinese("aaaa")

            java.util.NoSuchElementException: key not found: aaaa

              at scala.collection.MapLike$class.default(MapLike.scala:228)

              at scala.collection.AbstractMap.default(Map.scala:59)

              at scala.collection.mutable.HashMap.apply(HashMap.scala:65)

              ... 32 elided

            scala> chinese.get("Andy1231312")

            res21: Option[Int] = None

         

         

            chinese("aaaa") get("Andy1231312")

             

            需求:判断key是否存在,若不存在,返回默认值

             

            scala> if(chinese.contains("aaa")){

                 | chinese("aaa")

                 | }else{

                 | -1

                 | }

            res22: Int = -1

             

            scala> chinese.getOrElse("aaaa",-1)

            res23: Int = -1

         

        2、更新映射中的值

         

            注意:必须是可变映射

             

            scala> chinese

            res24: scala.collection.mutable.Map[String,Int] = Map(Tom -> 80, Andy -> 70)

            scala> chinese("Andy")=20

            scala> chinese

            res26: scala.collection.mutable.Map[String,Int] = Map(Tom -> 80, Andy -> 20)

             

             

        3、映射的迭代

            for foreach

             

            scala> chinese

            res27: scala.collection.mutable.Map[String,Int] = Map(Tom -> 80, Andy -> 20)

            scala> for(s<-chinese) println(s)

            (Tom,80)

            (Andy,20)

            scala> chinese.foreach(println)

            (Tom,80)

            (Andy,20)

             

            foreach  高阶函数

             

十、元组 : Tuple

     

    scala 中的tuple : 是不同类型值的集合

     

    scala> val t1 = Tuple("Tom","Lily",1)

    <console>:14: error: not found: value Tuple

           val t1 = Tuple("Tom","Lily",1)

                    ^

    scala> val t1 = Tuple3("Tom","Lily",1)

    t1: (String, String, Int) = (Tom,Lily,1)

     

    Tuple3 代表 Tuple中有三个元素

    scala> val t1 = Tuple2("Lily",1)

    t1: (String, Int) = (Lily,1)

    scala> val t2 = (1,2,4,"Hello")

    t2: (Int, Int, Int, String) = (1,2,4,Hello)

     

     

    tuple操作:

     

    访问tuple中的元素

    scala> val t1 = Tuple3("Tom","Lily",1)

    t1: (String, String, Int) = (Tom,Lily,1)

    scala> t1.

    _1   _3         copy     hashCode   productArity     productIterator   toString   zipped

    _2   canEqual   equals   invert     productElement   productPrefix     x

    scala> t1._1

    res30: String = Tom

    scala> t1._3

    res31: Int = 1

     

    如何遍历Tuple中的元素

        注意:Tuple并没有提供一个foreach函数,我们使用productIterator

         

     

    遍历分为两步:

    1、使用 productIterator 生成一个迭代器

    2、遍历

     

    scala> t1.productIterator.

    !=                copyToBuffer   forall               min                reduceRightOption   toIterable

    ##                corresponds    foreach              minBy              sameElements        toIterator

    +                 count          formatted            mkString           scanLeft            toList

    ++                drop           getClass             ne                 scanRight           toMap

    ->                dropWhile      grouped              next               seq                 toSeq

    /:                duplicate      hasDefiniteSize      nonEmpty           size                toSet

    :\                ensuring       hasNext              notify             slice               toStream

    ==                eq             hashCode             notifyAll          sliding             toString

    GroupedIterator   equals         indexOf              padTo              span                toTraversable

    addString         exists         indexWhere           partition          sum                 toVector

    aggregate         filter         isEmpty              patch              synchronized        wait

    asInstanceOf      filterNot      isInstanceOf         product            take                withFilter

    buffered          find           isTraversableAgain   reduce             takeWhile           zip

    collect           flatMap        length               reduceLeft         to                  zipAll

    collectFirst      fold           map                  reduceLeftOption   toArray             zipWithIndex

    contains          foldLeft       max                  reduceOption       toBuffer            →

    copyToArray       foldRight      maxBy                reduceRight        toIndexedSeq

     

    scala> t1.productIterator.foreach(println)

    Tom

    Lily

    1

     

十一、scala中的文件操作

    类似于java的io

    举例:

    1、读取文件

    2、读取二进制文件

    3、从url中获取信息

    4、写入文件

     

    5、scala中调用java的类库

     

    见代码

---------------Scala面向对象-------------------------- 

scala是一个多范式的编程语言(支持多种方式的编程)

类似于 java 有区别

一、面向对象的概念

    1、封装 : 把属性和操作属性的方法,写在了一起。class

    2、继承

    3、多态

     

    java中面向对象的概念,也是用与scala

二、定义类:class

    举例:创建一个学生类

     

三、内部类(嵌套类):在一个类的内部,定义了另外一个类

    见代码

四、类的构造器:两种

    1、主构造器 : 和类的声明在一起,并且一个类只能有一个主构造器

     

         class Course(var courseName:String,var grade : Int)

     

    2、辅助构造器 : 一个类可以有多个辅助构造器,通过this来实现

     

五、object对象:相当于java中的static

    1、Object 对象中的内容都是静态的

    2、如果和类名相同,则成为伴生对象

    3、scala中没有static关键字

     

    4、举例

        (1)使用object来实现单例模式:一个类里面只有一个对象

            在java中,把类的构造器定义成private的,并且提供一个getInstance,返回对象

            在scala中,使用object实现

             

        (2)使用App对象:应用程序对象。

            好处:可以省略main方法。

     

六、apply方法

    val t1 = Tuple3("Tom","Lily",1)

    没有new关键字,但是也创建出来对象,用了apply方法

     

    注意:apply方法必须写在伴生对象中。

     

七、继承

    1、extends 和java一样

        object HelloWorld extends App

         

    2、抽象类:代码中

     

     

    抽象字段:

     

    package day0323

    /**

      * Created by root on 2019/3/23.

      *

      * 抽象字段  抽象属性

      *

      * 定义: 没有初始值的字段

      */

    abstract class  Person1{

      //定义抽象字段

      val id :Int

      val name : String

    }

    如果不加abstract 报错

    abstract class Employee1 extends Person1{

    }

     

    下面两种方式均不会报错

    class Employee2() extends Person1{

      val id :Int = 1

      val name : String = ""

    }

     

    class Employee2(val id:Int,val name:String) extends Person1{

       

    }

    object Demo3 {

}

八、特质(trait): 抽象类,支持多重继承

    本质:scala 的一个抽象类

    trait

     

    关键字:extends Human with  Action

     

九、包和包对象:参考讲义

    package

    package object

     

---------------Scala函数式编程--------------------------    

多范式:面向对象,函数式编程(程序实现起来简单)

举例:WordCount

sc 是 SparkContext , 非常重要

一行:

var result =

sc.textFile("hdfs://xxxx/xxx/data.txt")

.flatMap(_.split(" "))

.map((_,1))

.reduceByKey(_+_)

.collect

一、复习函数:关键字 def

二、匿名函数:没有名字的函数

    举例:

    scala> var myarray = Array(1,2,3)

    myarray: Array[Int] = Array(1, 2, 3)

    scala> def fun1(x:Int):Int = x*3

    fun1: (x: Int)Int

    scala> (x:Int) => x*3

    res0: Int => Int = <function1>

     

    问题:怎么去调用?高阶函数

    scala> fun1(3)

    res1: Int = 9

    scala> myarray.foreach(println)

    1

    2

    3

    scala> myarray.map((x:Int) => x*3)

    res3: Array[Int] = Array(3, 6, 9)

    (_,1)  (_+_) 都是匿名函数。

     

三、高阶函数(带有函数参数的函数):把一个函数作为另外一个函数的参数值

    定义一个高阶函数:

    对10做某种运算

    scala> def someAction(f:(Double)=>(Double)) = f(10)

    someAction: (f: Double => Double)Double

     

    解释:

    (Double)=>(Double)  代表了f 的类型:入参是double,返回值也是double的函数

     

    scala> someAction(sqrt)

    res5: Double = 3.1622776601683795

    scala> someAction(sin)

    res6: Double = -0.5440211108893698

    scala> someAction(cos)

    res7: Double = -0.8390715290764524

    scala> someAction(println)

    <console>:16: error: type mismatch;

     found   : () => Unit

     required: Double => Double

           someAction(println)

                  ^

    def someAction(f:(Double)=>(Double)) = f(10)

     

    someAction(sqrt) = sqrt(10)

     

四、高阶函数的实例

    scala中提供了常用的高阶函数。

     

    (*)map : 相当于一个循环,对某个集合中的每个元素都进行操作(接收一个函数),返回一个新的集合。

     

    scala> var numers = List(1,2,3,4,5,6,7,8,9,10)

    numers: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

     

    scala> numers.map((i:Int)=>i*2)

    res9: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)

    scala> numers.map(_*2)

    res10: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)

     

    说明:

    (i:Int)=>i*2  与  _*2   等价的。

     

    (i:Int,j:Int)=>i+j    _+_

     

    scala> numers

    res11: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

     

    不改变numbers本身的值。

     

    (*)foreach:相当于一个循环,对某个集合中的每个元素都进行操作(接收一个函数),不返回结果。

    scala> numers.foreach(println)

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

     

    numers.foreach(_*2) 

    没有返回值。

     

     

    (*) filter :过滤,选择满足的数据

        举例:查询能被2整除的数字

         

        scala> numers.filter((i:Int)=>i%2==0)

        res14: List[Int] = List(2, 4, 6, 8, 10)

         

        filter函数,参数要求:要求一个返回 bool 值的函数,筛选出所有为true的数据。

         

    (*)zip操作:合并两个集合

     

    scala> numers.filter((i:Int)=>i%2==0)

    res14: List[Int] = List(2, 4, 6, 8, 10)

    scala> List(1,2,3).zip(List(4,5,6))

    res15: List[(Int, Int)] = List((1,4), (2,5), (3,6))

    scala> List(1,2,3).zip(List(4,5))

    res16: List[(Int, Int)] = List((1,4), (2,5))

    scala> List(1).zip(List(4,5))

    res17: List[(Int, Int)] = List((1,4))

     

    (*)partition : 根据断言(就是某个条件,匿名函数)的结果,来进行分区

     

        举例:能被2整除的分成一个区,不能被2整除的分成另外一个区。

         

        scala> numers.partition((i:Int)=>i%2==0)

        res18: (List[Int], List[Int]) = (List(2, 4, 6, 8, 10),List(1, 3, 5, 7, 9))

         

    (*)find : 查找第一个满足条件的元素

     

        scala> numers.find(_%3==0)

        res19: Option[Int] = Some(3)

         

        _%3==0  (i:Int)=>i%3==0  一样

         

    (*)flatten:把嵌套的结果展开

        scala> List(List(2,4,6,8,10),List(1,3,5,7,9)).flatten

        res21: List[Int] = List(2, 4, 6, 8, 10, 1, 3, 5, 7, 9)

         

         

    (*)flatmap : 相当于一个 map + flatten

         

        scala> var myList = List(List(2,4,6,8,10),List(1,3,5,7,9))

        myList: List[List[Int]] = List(List(2, 4, 6, 8, 10), List(1, 3, 5, 7, 9))

        scala> myList.flatMap(x=>x.map(_*2))

        res22: List[Int] = List(4, 8, 12, 16, 20, 2, 6, 10, 14, 18)

         

        myList.flatMap(x=>x.map(_*2))

         

        执行过程:

        1、将 List(2, 4, 6, 8, 10), List(1, 3, 5, 7, 9) 调用 map(_*2) 方法。x 代表一个List

        2、flatten

     

五、概念:闭包、柯里化

         

    1、闭包:就是函数的嵌套

        在一个函数的里面,包含了另一个函数的定义

        可以在内函数中访问外函数的变量

         

        举例:

        def mulBy(factor:Double) = (x:Double)=>x*factor

                外                           内

                 

        乘以三:

        scala> def mulBy(factor:Double) = (x:Double)=>x*factor

        mulBy: (factor: Double)Double => Double

        scala> var triple = mulBy(3)

        triple: Double => Double = <function1>

         

        相当于 triple(x:Double) = x*3

         

        scala> triple(10)

        res23: Double = 30.0

        scala> triple(20)

        res24: Double = 60.0

        scala> var half = mulBy(0.5)

        half: Double => Double = <function1>

        scala> half(10)

        res25: Double = 5.0

         

        引入柯里化:

        scala> mulBy(3)(10)

        res26: Double = 30.0

         

    2、柯里化

        概念:柯里化函数:是把具有多个参数的函数,转化为一个函数链,每个节点上都是单一函数

         

        def add(x:Int,y:Int) = x+y

         

        def add(x:Int)(y:Int) = x+y

         

        转化步骤:

         

        原始:def add(x:Int,y:Int) = x+y

         

        闭包:def add(x:Int) = (y:Int) => x+y

         

        简写:def add(x:Int)(y:Int) = x+y

     

    scala> def add(x:Int)(y:Int) = x+y

    add: (x: Int)(y: Int)Int

    scala> add(1)(2)

    res27: Int = 3

---------------Scala集合-------------------------

比较简单

1、可变集合和不可变集合(Map)

    immutable mutable

    举例:

     

    scala> def math = scala.collection.immutable.Map("Tom"->80,"Lily"->20)

    math: scala.collection.immutable.Map[String,Int]

    scala> def math = scala.collection.mutable.Map("Tom"->80,"Lily"->20,"Mike"->95)

    math: scala.collection.mutable.Map[String,Int]

     

    集合的操作:

    获取集合中的值

     

    scala> math.get("Tom")

    res28: Option[Int] = Some(80)

    scala> math("Tom")

    res29: Int = 80

    scala> math("Tom12312312")

    java.util.NoSuchElementException: key not found: Tom12312312

      at scala.collection.MapLike$class.default(MapLike.scala:228)

      at scala.collection.AbstractMap.default(Map.scala:59)

      at scala.collection.mutable.HashMap.apply(HashMap.scala:65)

      ... 32 elided

    scala> math.get("Tom123123123")

    res31: Option[Int] = None

    scala> math.contains("Tom123123123")

    res32: Boolean = false

    scala> math.getOrElse("Tom123123123",-1)

    res33: Int = -1

     

     

    更新集合中的值:注意:必须是可变集合

     

    scala> math

    res34: scala.collection.mutable.Map[String,Int] = Map(Mike -> 95, Tom -> 80, Lily -> 20)

    scala> math("Tom")=0

    scala> math

    res36: scala.collection.mutable.Map[String,Int] = Map(Mike -> 95, Tom -> 80, Lily -> 20)

     

    造成上述现象的原因,没有import包,如果import以后,问题解决:

     

    scala> import scala.collection.mutable._

    import scala.collection.mutable._

    scala> var math = Map("Tom"->80,"Lily"->20,"Mike"->95)

    math: scala.collection.mutable.Map[String,Int] = Map(Mike -> 95, Tom -> 80, Lily -> 20)

    scala> math("Tom")=0

    scala> math

    res1: scala.collection.mutable.Map[String,Int] = Map(Mike -> 95, Tom -> 0, Lily -> 20)

     

     

    添加新的元素

     

    scala> math += "Bob"->85

    res38: scala.collection.mutable.Map[String,Int] = Map(Bob -> 85, Mike -> 95, Tom -> 80, Lily -> 20)

     

    移出一个元素

    scala> math -= "Bob"

    res39: scala.collection.mutable.Map[String,Int] = Map(Mike -> 95, Tom -> 80, Lily -> 20)

     

2、列表:可变列表,不可变列表

     

    不可变列表 List

     

    scala> myList.head

    res40: Int = 1

    scala> myList.tail

    res41: List[Int] = List(2, 3)

     

    注意:tail 是除了第一个元素外,其他的元素

     

    可变列表:LinedList  在 scala.collection.mutable 包中

     

    scala> var myList = scala.collection.mutable.LinkedList(1,2,3,4)

    warning: there was one deprecation warning; re-run with -deprecation for details

    myList: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2, 3, 4)

     

    需求:把上面列表中,每一个元素都乘以2

     

    游标,指向列表的开始

     

    var cur = myList

     

    while(cur != Nil ){

     

    //把当前元素乘以2

    cur.elem = cur.elem*2

     

    //移动指针到下一个元素

    cur = cur.next

    }

     

    scala> var cur = myList

    cur: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2, 3, 4)

    scala> while(cur != Nil ){

         | cur.elem = cur.elem*2

         | cur = cur.next

         | }

    scala> myList

    res43: scala.collection.mutable.LinkedList[Int] = LinkedList(2, 4, 6, 8)

     

    scala> myList.map(_*2)  

    warning: there was one deprecation warning; re-run with -deprecation for details

    res44: scala.collection.mutable.LinkedList[Int] = LinkedList(4, 8, 12, 16)

     

3、序列

    (*)数据库中也有序列:sequence 、 auto increment

        (1)作为主键,实现自动增长

        (2)提高性能,序列在Oracle是在内存中的

         

    (*)Vector Range

         

        举例:

        Vector 是一个带下标的序列,我们可以通过下标来访问Vector中的元素

         

        Range : 是一个整数的序列

        scala> Range(0,5)

        res45: scala.collection.immutable.Range = Range(0, 1, 2, 3, 4)

         

        从0开始,到5 ,但不包括5

         

        scala> println(0 until 5)

        Range(0, 1, 2, 3, 4)

         

        scala> println(0 to 5)

        Range(0, 1, 2, 3, 4, 5)

         

        Range可以相加

        scala> ('0' to '9') ++ ('A' to 'Z')

        res48: scala.collection.immutable.IndexedSeq[Char] = Vector(0, 1, 2, 3, 4, 5, 6, 7, 8, 9,

        A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U

        , V, W, X, Y, Z)

         

        把Range转换成list

        scala> 1 to 5 toList

        warning: there was one feature warning; re-run with -feature for details

        res49: List[Int] = List(1, 2, 3, 4, 5)

         

4、集(Set) : 不重复元素的集合,默认是HashSet,与java类似

    scala> var s1 = Set(1,2,10,8)

    s1: scala.collection.immutable.Set[Int] = Set(1, 2, 10, 8)

    scala> s1 + 10

    res50: scala.collection.immutable.Set[Int] = Set(1, 2, 10, 8)

    scala> s1 + 7

    res51: scala.collection.immutable.Set[Int] = Set(10, 1, 2, 7, 8)

    scala> s1

    res52: scala.collection.immutable.Set[Int] = Set(1, 2, 10, 8)

     

    创建一个可排序的Set SortedSet

     

    scala> var s2 = scala.collection.mutable.SortedSet(1,2,3,10,8)

    s2: scala.collection.mutable.SortedSet[Int] = TreeSet(1, 2, 3, 8, 10)

     

    判断元素是否存在

    scala> s2.contains(1)

    res53: Boolean = true

    scala> s2.contains(1231231)

    res54: Boolean = false

     

    集的运算:

    union并集 intersect 交集  diff 差集

    scala> var s1 = Set(1,2,3,4,5,6)

    s1: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 3, 4)

    scala> var s2 = Set(5,6,7,8,9,10)

    s2: scala.collection.immutable.Set[Int] = Set(5, 10, 6, 9, 7, 8)

    scala> s1 union s2

    res55: scala.collection.immutable.Set[Int] = Set(5, 10, 1, 6, 9, 2, 7, 3, 8, 4)

    scala> s1 intersect s2

    res56: scala.collection.immutable.Set[Int] = Set(5, 6)

    scala> s1 diff s2

    res57: scala.collection.immutable.Set[Int] = Set(1, 2, 3, 4)

     

    数据库里面的union操作,要求:

    列数一样

    列的类型一样

     

    select A,B from ****

    union

    select C,D from *****

     

    python

    pyspark

5、模式匹配:相当于java中的switch case语句 但是 功能更强大

6、样本类  

    定义: case class

     

    作用:

    (1)支持模式匹配,instanceof

    (2)定一个 Spark SQL 中的 schema : 表结构

    scala> class Fruit

    defined class Fruit

    scala> class Banana(name:String) extends Fruit

    defined class Banana

    scala> class Apple(name:String) extends Fruit

    defined class Apple

    scala> var a = new Apple("Apple")

    a: Apple = Apple@7e446d92

    scala> println(a.instanceOf[Fruit])

    <console>:15: error: value instanceOf is not a member of Apple

           println(a.instanceOf[Fruit])

                     ^

    scala> println(a.isInstanceOf[Fruit])

    true

    scala> println(a.isInstanceOf[Banana])

    <console>:16: warning: fruitless type test: a value of type Apple cannot also be a Banana

           println(a.isInstanceOf[Banana])

                                 ^

    false

     

---------------Scala高级特性-------------------------  

一、泛型

和java类似 T

    1、泛型类:定义类的时候,可以带有一个泛型的参数

     

    2、泛型函数:定义一个函数,可以带有一个泛型的参数

     

         

    scala> def mkIntArray(elem:Int*)=Array[Int](elem:_*)

    mkIntArray: (elem: Int*)Array[Int]

    scala> mkIntArray(1,2,3)

    res5: Array[Int] = Array(1, 2, 3)

    scala> mkIntArray(1,2,3,4,5)

    res6: Array[Int] = Array(1, 2, 3, 4, 5)

    scala> def mkIntArray(elem:String*)=Array[String](elem:_*)

    mkIntArray: (elem: String*)Array[String]

    scala> def mkStringArray(elem:String*)=Array[String](elem:_*)

    mkStringArray: (elem: String*)Array[String]

    scala> mkStringArray("a","b")

    res7: Array[String] = Array(a, b)

    scala> def mkArray[T:ClassTag]

     

    ClassTag : 表示scala在运行时候的状态信息,这里表示调用时候数据类型

    scala> def mkArray[T:ClassTag](elem:T*) = Array[T](elem:_*)

    mkArray: [T](elem: T*)(implicit evidence$1: scala.reflect.ClassTag[T])Array[T]

    scala> mkArray(1,2)

    res8: Array[Int] = Array(1, 2)

    scala> mkArray("Hello","aaa")

    res9: Array[String] = Array(Hello, aaa)

     

    scala> mkArray("Hello",1)

    res10: Array[Any] = Array(Hello, 1)

     

    泛型:但凡有重复的时候,考虑使用泛型

    3、上界和下界

         

        Int x

        规定x的取值范围  100 <= x <=1000

         

        泛型的取值范围:

        T

         

        类的继承关系  A ---> B  ---> C ---> D 箭头指向子类

         

        定义T的取值范围   D   <:     T     <:  B

         

        T 的 取值范围 就是 B C D

         

        <: 就是上下界的表示方法

         

        概念

        上界  S <: T  规定了 S的类型必须是 T的子类或本身

        下界  U >: T  规定了 U的类型必须是 T的父类或本身

        scala> def mkIntArray(elem:Int*)=Array[Int](elem:_*)

        mkIntArray: (elem: Int*)Array[Int]

        scala> mkIntArray(1,2,3)

        scala> def addTwoString[T <: String](x:T,y:T) = x +" ********* " + y

        addTwoString: [T <: String](x: T, y: T)String

        scala> addTwoString("Hello","World")

        res11: String = Hello ********* World

        scala> addTwoString(1,2)

        <console>:14: error: inferred type arguments [Int] do not conform to method addTwoString's type parameter bounds [T <: String]

               addTwoString(1,2)

               ^

        <console>:14: error: type mismatch;

         found   : Int(1)

         required: T

               addTwoString(1,2)

                            ^

        <console>:14: error: type mismatch;

         found   : Int(2)

         required: T

               addTwoString(1,2)

                              ^

        scala> addTwoString(1.toString,2.toString)

        res13: String = 1 ********* 2

     

     

    4、视图界定 View bounds

     

        就是上界和下界的扩展

         

        除了可以接收上界和下界规定的类型以外,还可以接收能够通过隐式转换过去的类型

         

        用 % 来表示

         

        scala>  def addTwoString[T <% String](x:T,y:T) = x +" ********* " + y

        addTwoString: [T](x: T, y: T)(implicit evidence$1: T => String)String

        scala> addTwoString(1,2)

        <console>:14: error: No implicit view available from Int => String.

               addTwoString(1,2)

                           ^

        scala> implicit def int2String(n:Int):String = n.toString

        warning: there was one feature warning; re-run with -feature for details

        int2String: (n: Int)String

        scala> addTwoString(1,2)

        res15: String = 1 ********* 2

         

        执行过程:

        1、调用了 int2String  Int => String

        2、addTwoString("1","2")

         

     

    5、协变和逆变(概念)

     

        了解概念。

         

        概念:

        协变:表示在类型参数前面加上 + 。泛型变量的值,可以是本身类型或者其子类类型。

        逆变:表示在类型参数前面加上 - 。泛型变量的值,可以是本身类型或者其父类类型。

二、隐式转换

    1、隐式转换函数: implicit

     

    见代码

     

    2、隐式参数:使用implicit 修饰的函数参数

     

        定义一个带有隐式参数的函数:

        scala> def testPara(implicit name:String) = println("The value is " + name)

        testPara: (implicit name: String)Unit

        scala> testPara("AAAAAAAAAAAA")

        The value is AAAAAAAAAAAA

        scala> implicit val name : String = "*******************"

        name: String = *******************

        scala> testPara

        The value is *******************

         

        定义一个隐式参数,找到两个值中比较小的那个值

        100  23   -->23

        "Hello"  "ABC"  --> ABC

         

        scala> def smaller[T](a:T,b:T)(implicit order : T => Ordered[T]) = if(a<b) a else b

        smaller: [T](a: T, b: T)(implicit order: T => Ordered[T])T

        scala> smaller(1,2)

        res18: Int = 1

        scala> smaller("Hello","ABC")

        res19: String = ABC

         

        解释:

        order 就是一个隐式参数,我们使用Scala中的 Ordered 类,表示该值可以被排序,也就是可以被比较

         

        作用:扩充了属性的功能

         

    3、  隐式类 在类名前 加 implicit 关键字

        作用:扩充类的功能

         

AKKA 项目  --> scala  主从通信

Spark:Core RDD SQL Streaming 调优 java虚拟机的调优 MLLib

flink kafka

第1章,“可伸展的语言”,给出了Scala的设计,和它后面的理由,历史的概要。 第2章,“Scala的第一步”,展示给你如何使用Scala完成若干种基本编程任务,而不牵涉过多关于如何工作的细节。本章的目的是让你的手指开始敲击并执行Scala代码。 第3章,“Scala的下一步”,演示更多的基本编程任务来帮助你更快速地上手Scala。本章之后,你将能够开始在简单的脚本任务中使用Scala。 第4章,“类和对象”,通过描述面向对象语言的基本建设模块和如何编译及运行Scala程序的教程开始有深度地覆盖Scala语言。 第5章,“基本类型和操作”,覆盖了Scala的基本类型,它们的文本,你可以执行的操作,优先级和关联性是如何工作的,还有什么是富包装器。 第6章,“函数式对象”,进入了Scala面向对象特征的更深层次,使用函数式(即,不可变)分数作为例子。 第7章,“内建控制结构”,显示了如何使用Scala的内建控制结构,如,if,while,for,try和match。 第8章,“函数和闭包”,深度讨论了函数式语言的基础建设模块,函数。 ...... 第31章,“组合子解析”,显示了如何使用Scala的解析器组合子库来创建解析器。 第32章,“GUI编程”,展示了使用Scala库简化基于Swing的GUI编程的快速旅程。 第33章,“SCell电子表”,通过展示一个完整的电子表的实现,集中演示了Scala的一切。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_38220914

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值