01-尚硅谷大数据技术之Scala.docx

基础篇

  • 下划线的作用:

    • 声明变量,但是不能访问val _ ="zhangsan"
    • 将函数作为整体使用 val f = fun1 _
    • 使用import语法时,下划线可以代替星号
    • 使用import语法时,下划线可以隐藏类import java.sql.{Date=>_}

      变量

  • 变量定义之后必须进行初始化

  • var定义后的变量,变量类型无法改变

    1. object ScalaVariable {
    2. def main(args: Array[String]): Unit = {
    3. // var | val 变量名 :变量类型 = 变量值
    4. // 其中var为可变变量,val为不可变变量相当于Java的final
    5. var username : String = "zhangsan"
    6. val userpswd : String = "000000"
    7. var username = "zhangsan" // 如果变量的类型如果能够通过变量值推断出来,那么可以省略类型声明
    8. }
    9. }

    字符串

    1. object ScalaString {
    2. def main(args: Array[String]): Unit = {
    3. val name : String = "scala"
    4. val subname : String = name.substring(0,2) //分割字符串
    5. printf("name=%s\n", name)// 传值字符串(格式化字符串)
    6. println(s"name=${name}") //插值字符串
    7. println( //多行字符串,用来封装json数据和sql语句比较常用
    8. s"""
    9. | Hello
    10. | ${name}
    11. """.stripMargin)//stripMargin默认是“|”作为出来连接符,在多行换行的行头前面加一个“|”符号即可。
    12. }
    13. }

    输入输出

    1. object ScalaIn {
    2. def main(args: Array[String]): Unit = {
    3. val age : Int = scala.io.StdIn.readInt()// 从命令行输入
    4. //从文件输入,相对路径是从项目的路径开始
    5. scala.io.Source.fromFile("input/user.json").foreach(
    6. line => {
    7. print(line)
    8. }
    9. )
    10. scala.io.Source.fromFile("input/user.json").getLines()
    11. //输出
    12. val writer = new PrintWriter(new File("output/test.txt" ))
    13. writer.write("Hello Scala")
    14. writer.close()
    15. }
    16. }

    数据类型

    image.pngimage.png
    nothing是scala语言中特殊类型,用于统一方法的异常和正常返回
    Any相当于Java的Object

    流程控制

    循环

    for循环、while循环和do…while循环 ```java 基本语法 for ( 循环变量 <- 数据集 ) { 循环体 }

object ScalaLoop { def main(args: Array[String]): Unit = { for ( i <- Range(1,5,2) ) { // 范围集合,循环步长 println(“i = “ + i ) } for ( i <- 1 to 5 if i!=3) { // 包含5,循环守卫 println(“i = “ + i ) } for ( i <- 1 until 5 ) { // 不包含5 println(“i = “ + i ) }

  1. //循环嵌套
  2. for ( i <- Range(1,5); j <- Range(1,4) ) { //相当于两重循环
  3. println("i = " + i + ",j = " + j )
  4. }
  5. //引入变量
  6. for ( i <- Range(1,5); j = i - 1 ) {
  7. println("j = " + j )
  8. }
  9. //循环返回值
  10. val result = for ( i <- Range(1,5) ) yield {
  11. i * 2
  12. }
  13. println(result)
  14. }

}

```java
object ScalaLoop {
    def main(args: Array[String]): Unit = {
        scala.util.control.Breaks.breakable { //在循环体外面嵌套一层函数
            for ( i <- 1 to 5 ) {
                if ( i == 3 ) {
                    scala.util.control.Breaks.break //需要中断的地方
                }
                println(i)
            }
        }
    }
}

函数

object ScalaFunction {
    def main(args: Array[String]): Unit = {
    //无参,有返回值
    def fun2(): String = {
            "zhangsan"
        }
        println( fun2() )

    // 有参,无返回值
    def fun3( name:String ): Unit = {
            println( name )
        }
        fun3("zhangsan")

    //有参,有返回值
     def fun4(name:String): String = {
            "Hello " + name
        }
        println( fun4("zhangsan") ) 

    //可变参数,可变参数不能放置在参数列表的前面,一般放置在参数列表的最后
    def fun7(id:String="000",names:String*): Unit = { //id包含参数默认值
            println(names)
        }
        fun7(id="zhangsan" )
        fun7( "zhangsan", "lisi" )




    }
}

所谓的至简原则,其实就是Scala的作者为了开发人员能够大幅度提高开发效率。通过编译器的动态判定功能,帮助我们将函数声明中能简化的地方全部都进行了简化。也就是说将函数声明中那些能省的地方全部都省掉。所以这里的至简原则,简单来说就是:能省则省。

  • 省略了return关键字
  • 省略了花括号,如果函数只有一行
  • 省略返回值类型 ```java 如果函数体中有明确的return语句,那么返回值类型不能省略 如果函数体返回值类型明确为Unit, 那么函数体中即使有return关键字也不起作用 如果函数体返回值类型声明为Unit, 但是又想省略,那么此时就必须连同等号一起省略

object ScalaFunction { def main(args: Array[String]): Unit = { //省略等号 def fun5() { return “zhangsan” } println(fun5()) //省略名称和关键字 () => { println(“zhangsan”) } } }

<a name="jFsQ5"></a>
### 高级函数编程
```java
object scala3 {
  def main(args: Array[String]): Unit = {
    def fun1():Unit={println("zhangsan ")}
    def test1(name:String) :String={"123"}

    //1.将函数作为对象使用
    //函数作为对象使用,当函数独立使用时,参数声明个数没有限制,但是作为对象给别人使用时参数最多为22个
    val f2 =fun1 //相当于fun1()
    //函数类型的另一种写法:(输入参数类型)=>输出类型
    // 之所以使用下划线让函数作为对象使用,因为代码中没有明确变量的类型,所以需要通过取值来判断,如果变量声明的类型作为函数类型,那么可以不使用下划线让函数作为对象
    val f1 :Function0[Unit]=fun1  //其中Function0[Unit]可以省略,为函数类型,等价于f1=fun1 _
    val f3:(String)=>String=test1
//    println(f1)

    //2.将函数作为参数来使用
    def test(f:()=>Unit):Unit={
      f()
    }
    test(fun1 _)

    //3.将函数作为返回值返回,一般应用于将内部的函数在外部使用
    def test2() :Unit={
      println("function...")
    }

    def fun():()=>Unit={
      test2 _
    }
    fun()()
  }
}

面向对象编程

object关键字声明的类和对象有关,这个对象等同于伴随着这个类创建时所产生,所以将这个对象称为伴生对象,伴生对象就是一个对象,可以访问伴生类中的所有东西,包括私有的,伴生对象就是模拟静态方法产生的,一般写代码时,将静态语法操作的代码写在伴生对象中,将成员方法或属性写在伴生类中。
使用class定义的内容和属性需要创建对象才能用,而object定义的内容可以直接通过类名进行静态访问

class User {
    var name : String = _
    val age : Int = 30
    private val email : String = _
    @BeanProperty var address : String = _ //将该属性设置符合bean规范,可以用get、set获取值
}
//构造方法
//辅助构造方法在执行之前,应该首先调用主构造方法完成类的初始化
class User() { // 主构造函数,用于完成类的初始化操作
    var username : String = _ 
    def this( name:String ) { // 辅助构造函数,使用this关键字声明
        this() // 辅助构造函数应该直接或间接调用主构造函数
        username = name
    }
    def this( name:String, password:String ) {
        this(name) // 构造器调用其他另外的构造器,要求被调用构造器必须提前声明
    }
}
//继承
class Person {
}
class User extends Person {
}
如果类名和伴生对象名称保持一致,那么这个类称之为伴生类。
Scala编译器可以通过伴生对象的apply方法创建伴生类对象。
apply方法可以重载,并传递参数,且可由Scala编译器自动识别。
所以在使用时,其实是可以省略的。
class User { // 伴生类
}
object User { // 伴生对象
    def apply() = new User() // 构造伴生类对象
}
...
val user1 = new User()// 通过构造方法创建对象
Val user2 = User.apply() // 通过伴生对象的apply方法构造伴生类对象 
val user3 = User() // scala编译器省略apply方法,自动完成调用
//覆盖重写 override
object scala1 {
  def main(args: Array[String]): Unit = {
    abstract class User{
      def test():Unit={

      }
    }
    class Child extends User{
      override def test(): Unit = {
        println("重写方法")
      }
    }
  }
}