Scala学习笔记

本文详细介绍了Scala编程的基础知识,包括变量、常量、流程控制、函数、类、对象、特质、集合操作等,并展示了如何使用匿名函数、闭包、元组和模式匹配。此外,还探讨了Scala中的枚举、类型系统、可变与不可变集合以及并行执行等高级特性。
摘要由CSDN通过智能技术生成

Scala学习笔记


第一个scala程序
**
 * object: 关键字,声明一个单例对象(伴生对象)
 */
object HelloWorld {

  /**
   * main: 方法,从外部可以直接调用执行的方法
   * def 方法名称(参数名称: 参数类型): 返回值类型 = {方法体}
   * []: 泛型
   * @param args
   */
  def main(args: Array[String]): Unit = {
    println("hello world")
    System.out.println("hello scala from java")
  }
}
Scala和Java的区别
/**
 * java实现
 */
public class Student {
    private String name;
    private int age;
    private static String school = "学校";

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void printInfo(){
        System.out.println(this.name + " " + this.age + " " + Student.school);
    }

    public static void main(String[] args) {
        Student student1 = new Student("张三", 23);
        Student student2 = new Student("李四", 24);
        student1.printInfo();
        student2.printInfo();
    }
}

/**
 * Scala实现
 * student(入口类),伴生类;student$(伴生类),伴生对象所属类
 * 伴生类,伴生对象,同时实现,必须名称一样,在同一个文件内
 * @param name
 * @param age
 */
class Student(name: String, age: Int) {
  def printInfo(): Unit = {
    println(name + " " + age + " " + Student.school)
  }
}

//引入伴生对象
object Student{
  val school: String = "学校"

  def main(args: Array[String]): Unit = {
    val student1 = new Student("张三", 23)
    val student2 = new Student("李四", 23)
    student1.printInfo()
    student2.printInfo()
  }
}
变量和常量(能用常量的地方不用变量)
  1. 变量基本语法: var 变量名 [: 变量类型] = 初始值, var i: Int = 10
  2. 常量基本语法: val 常量名 [: 常量类型] = 初始值, val j: Int = 20
  3. 声明变量时,类型可以省略,编译器自动推导,即类型推导
  4. 类型确定后,就不能修改,说明scala是强数据类型语言
  5. 变量声明时,必须要有初始值
  6. 在声明|定义一个变量时,可以使用var或者val来修饰,var修饰的变量可改变,val修饰的变量不可改
  7. “*” :用于将一个字符串复制多次拼接"a" * 3 输出 “aaa”
  8. printf:格式化输出
  9. s" " : 模板字符串
  10. f" ":格式化模板字符串
  11. raw" ": 按原始字符串输出
  12. 三引号表示字符串,保持多行字符串的原格式输出
	val name: String = "张三"
    val age: Int = 25
    println(s"我叫${name}今年${age}岁")

    val num: Double = 2.1231
    println(f"The num is ${num}%2.2f")
    println(raw"The num is ${num}%2.2f")

	val sql =
      s"""
         |select *
         |from test
         |where name = ${name}
         |and age > ${age}
         |""".stripMargin   //stripMargin:忽略编辑
    println(sql)
    ————————————————————————————————————输出
    我叫张三今年25The num is 2.12
	The num is 2.1231%2.2f

	select *
	from test
	where name = 张三
	and age > 25
键盘输入
import scala.io.StdIn

object Test02 {
  def main(args: Array[String]): Unit = {
    println("请输入名字:")
    val name: String = StdIn.readLine()
    println("请输入年龄")
    val age = StdIn.readInt()
    println(s"欢迎${age}岁的${name}")
  }
}
文件读写
import java.io.{File, PrintWriter}
import scala.io.Source

object Test03_FileIo {
  def main(args: Array[String]): Unit = {
    //从文件中读取数据
    Source.fromFile("src/main/resources/test.txt").foreach(print)

    //将数据写入文件
    val writer = new PrintWriter(new File("src/main/resources/output.txt"))
    writer.write("hello Scala from java writer")
    writer.close()
  }
}
数据类型

在这里插入图片描述
在这里插入图片描述

整数类型
  1. Byte::1字节
  2. Short::2字节
  3. Int:4字节
  4. Long:8字节
  5. Boolean:1个字节
  6. 整数默认类型:Int
  7. 浮点类型默认:Double
  8. Nothing:Nothing类型在scala的类层级最低端,它是任何其他类型的子类型,当一个函数,我们确定没有正常的返回值,我们就可以用nothing来指定返回类型,这样有一个好处,就是我们可以把返回的值(异常)赋给其他的函数或者变量(兼容性)
流程控制
import scala.util.control.Breaks
import scala.util.control.Breaks._

object Test04 {
  def main(args: Array[String]): Unit = {
    val i: Int = 100
    val y: Int = if (i < 12){
      println(i)
      1
    } else{
      println(i)
      2
    }
    println(y)

    //循环遍历
    for (i <- 1 to 10){
      println(i + "hello world")
    }

    for (i <- Range(0, 10)){
      println(i + "hello world")
    }

    for (i <- 0 until 10){
      println(i + "hello world")
    }
    println("----------------------")
    for (i <- Array(1,2,30,4)){
      println(i)
    }

    for (i <- List(1,2,30,4)){
      println(i)
    }

    for (i <- Set(1,2,30,4)){
      println(i)
    }

    //循环守卫,相当于java continue 功能
    for (i <- 1 to 10 if i != 3){
      println(i)
    }
    println("--------------------")
    //循环步长
    for (i <- 1 to 10 by 2){
      println(i)
    }

    println("-------------------------")
    for (i <- 10 to 1 by -1){
      println(i)
    }

    for (i <- 1 to 10 reverse){
      println(i)
    }

    //by 0.5 循环步长
    for ( i <- 1.0 to 10.0 by 0.5){
      println(i)
    }

    //嵌套循环
    for (i <- 1 to 3){
      for (j <- 1 to 3){
        println("i=" + i + ", j=" + j)
      }
    }

    println("--------------------------")
    for (i <- 1 to 5; j <- 1 to 4){
      println("i=" + i + ", j=" + j)
    }

    println("--------------------------")
    for (i <- 1 to 9){
      for (j <- 1 to i){
        print(s"$j + $i = ${i * j} \t")
      }
      println()
    }

    for (i <- 1 to 9; j <- 1 to i){
      print(s"$j + $i = ${i * j} \t")
      if (j == i) println()
    }
	
	//引入变量
    for (i <- 1 to 9; j = 9 -i){
      println(i + "---" + j)
    }

    for {
      i <- 1 to 5
      j = 5 - i
    }{
      println(i + "---" + j)
    }

    for (i <- 1 to 9; j = 9 - i){
      println(" " * j + "*" * (2 * i -1) )
    }

    for (i <- 1 to 9; stars = 2 * i -1; spaces = 9 -i){
      println(" " * spaces + "*" * stars)
    }

    for (stars <- 1 to 17 by 2; spaces = (17 - stars) / 2){
      println(" " * spaces + "*" * stars)
    }

    val b = for (i <- 1 to 10) yield i
    println(b)

	//跳出循环
    Breaks.breakable(
      for (i <- 1 until 5){
        if (i == 3){
          Breaks.break()
        }
        println(i)
      }
    )

    breakable(
      for (i <- 1 until 5){
        if (i == 3){
          break()
        }
        println(i)
      }
    )

  }

}
函数和方法的区别
  1. 为完成某一功能的程序语句的集合,称为函数
  2. 类中的函数称之方法
object Test05 {

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

    //可变参数
    def f1(str: String*): Unit = {
      println(str)
    }
    f1("a","b","c")
  }
  //多个参数,可变参数一般放置在最后
  def f2(str1: String, str2: String*): Unit = {
    println(s"str1=${str1}, str2=${str2}")
  }
  f2("a","b","c","d")

  //默认参数,一般放置在参数列表最后
  def f3(name: String = "李四"): Unit = {
    println(name)
  }
  f3()
  f3("王五")

  //带名参数
  def f4(name: String, age: Int): Unit = {
    println(s"名字是${name}今年${age}岁")
  }
  f4(age = 18, name = "张三")
}
函数至简原则

在这里插入图片描述
在这里插入图片描述

//匿名函数简化
  f((name) => {println(name)})
  f(name => {println(name)})
  f(name => println(name))
  f(println(_))
  //如果可以推断出,当前传入的println是一个函数体,而不是调用语句,可以直接省略下划线
  f(println)
object Test07 {
  def main(args: Array[String]): Unit = {
    val arr: Array[Int] = Array(12, 45, 75, 98)

    //对数组进行处理,将操作抽象出来,处理完毕之后的结果返回一个新的数组
    def arrayOperation(array: Array[Int], op: Int => Int): Array[Int] = {
      for (elem <- array) yield op(elem)
    }

    //定义一个加1操作
    def addOne(elem: Int): Int = {
      elem + 1
    }

    println(arrayOperation(arr, addOne).mkString(","))

    println(arrayOperation(arr, _ * 2).mkString(","))

    val fun = (i: Int, s: String, c: Char) => {
      if (i == 0 && s == "" && c == '0') false else true
    }
    println(fun(0, "", '0'))

    println(fun(1, "", '0'))

    println(fun(0, "", '1'))

    def f1(char: Char): Boolean={true}

    def f2(string: String): Char=>Boolean = {
      f1 _
    }

    def f3(i: Int): String=>(Char=>Boolean) = {
      def f2(s: String): Char=>Boolean = {
        def f1(c: Char): Boolean={
          if (i == 0 && s == "" && c == '0') false else true
        }
        f1
      }
      f2
    }

    println("------------------------------")
    println(f3(1)("")('0'))

    //简写
    def f4(i: Int): String=>(Char=>Boolean) = {
      s => c => if (i == 0 && s == "" && c == '0') false else true
    }

    //柯里化
    def f5(i: Int)(s: String)(c: Char): Boolean = {
      if (i == 0 && s == "" && c == '0') false else true
    }
  }

}
函数柯里化&闭包
  1. 闭包:函数式编程的标配
    1. 闭包:如果一个函数,访问到了它外部(局部)变量的值,那么这个函数和他所处的环境,称为闭包
    2. 函数柯里化:把一个参数列表的多个参数,变成多个参数列表
    3. 递归:一个函数/方法在函数/方法体内又调用了本身,我们称之为递归调用
object Test09 {

  def main(args: Array[String]): Unit = {
    println(fact(5))
    println(tailFact(5))
  }

  def fact(n: Int):Int = {
    if (n == 0) return 1;
    fact(n - 1) * n;
  }

  //尾递归
  def tailFact(n: Int): Int = {
    @tailrec
    def looop(n: Int, currRes: Int): Int = {
      if (n == 0) return currRes
      looop(n - 1, currRes * n)
    }
    looop(n, 1)
  }
}
控制抽象
  1. 值调用:把计算后的值传递过去
  2. 名调用:把代码传递过去
//1.传值调用
  def f0(a: Int): Unit = {
    println("a: " + a)
  }
  f0(1)

  //2.传名调用(传递代码块)
  def f1(a: =>Int): Unit = { // =>Int 表示代码块类型(一段代码块),返回值是Int
    println("a: " + a)
    println("a: " + a)
  }
  def f2(): Int = {
    println("f2调用")
    12
  }
  f1(f2())
实现while循环
object MyWhile {
  def main(args: Array[String]): Unit = {
    var n = 10
    while (n >= 1){
      println(n)
      n -= 1
    }
    //用闭包实现一个函数,将代码块作为参数传入,递归调用
    def myWhile(condition: =>Boolean): (=>Unit) =>Unit = {
      //内层函数需要递归调用
      def doLoop(op: => Unit): Unit = {
        if (condition){
          op
          myWhile(condition)(op)
        }
      }
      doLoop _
    }

    println("*********************")

    n = 10
    myWhile(n >= 1)({
      println(n)
      n -= 1
    })

    //用匿名函数实现
    def myWhile2(condition: =>Boolean): (=>Unit) =>Unit = {
      //内层函数需要递归调用
      op => {
        if (condition){
          op
          myWhile2(condition)(op)
        }
      }
    }

    println("*********************")

    n = 10
    myWhile2(n >= 1){
      println(n)
      n -= 1
    }

    //柯里化实现
    def myWhile3(condition: => Boolean)(op: => Unit): Unit = {
      if (condition){
        op
        myWhile3(condition)(op)
      }
    }
  }
}
惰性加载
  1. 当函数返回值被声明为lazy时,函数的执行将被推迟,直到我们首次对此取值,该函数才会执行,这种函数我们称之为惰性函数。
def main(args: Array[String]): Unit = {
    lazy val result:Int = sum(1, 2)
    println("1. 函数调用")
    println("2. result = " + result)
    println("4. result = " + result)
  }

  def sum(a: Int, b: Int): Int = {
    println("3. sum调用")
    a + b
  }
  
输出结果:
1. 函数调用
3. sum调用
2. result = 3
4. result = 3
面向对象

Scala的面向对象思想和Java的面向对象思想和概念是一致的。
Scala中语法和Java不同,补充了更多的功能。

  1. 包定义
//用嵌套风格定义包
package com{

  import com.pan.scala.Inner

  //在外层包中定义单例对象
  object Outer{
    var out: String = "out"

    def main(args: Array[String]): Unit = {
      println(Inner.in)
    }
  }
  package pan{
    package scala{
      //在内层包中定义单例对象
      object Inner{

        val in: String = "in"

        def main(args: Array[String]): Unit = {
          println(Outer.out)
          Outer.out = "outer"
          println(Outer.out)
        }
      }
    }
  }
}

//在同一文件中定义多个包
package a{
  package b{

    import com.pan.scala.Inner

    object Test{
      def main(args: Array[String]): Unit = {
        println(Inner.in)
      }
    }
  }
}
  1. 包对象
    1. 在Scala中可以为每个包定义一个同名的包对象,定义在包对象中的成员,作为其对应包下所有class和object的共享变量,可以被直接访问。
  2. 导包说明
    1. 通配符导入: import java.util._
    2. 给类起别名:import java.util.{ArrayList =>AL}
    3. 屏蔽类:import java.util.{ArrayList=> _ , _}
  3. 构造器
    1. Scala类的构造器包括:主构造器和辅助构造器
    2. 辅助构造方法不能直接构建对象,必须直接或间接调用主构造方法
//基本语法
class 类名(形参列表){  //主构造器
  //类体
  def this(形参列表){   //辅助构造器,可以有多个

  }
  def this(形参列表){

  }
}
  1. 构造器参数
    1. Scala类的主构造器函数的形参包括三种类型:未用任何修饰符,var修饰,val修饰
    2. 未用任何修饰符修饰:这个参数就是局部变量
    3. var修饰参数:作为类的成员属性使用,可以修改
    4. val修饰参数:作为类的只读属性使用,不能修改
object Test14 {
  def main(args: Array[String]): Unit = {
    val student2 = new Student2
    student2.name = "张三"
    student2.age = 15
    println(s"Student2: name = ${student2.name}, age = ${student2.age}")

    val student3 = new Student3("李四", 16)
    println(s"student3: name = ${student3.name}, age = ${student3.age}")

    val student4 = new Student4("李四1", 16)
    //println(s"student4: name = ${student4.name}, age = ${student4.age}")
    student4.printInfo()

    val student5 = new Student5("李四", 16)
    println(s"student5: name = ${student5.name}, age = ${student5.age}")

    val student6 = new Student6("李四", 16)
    println(s"student6: name = ${student6.name}, age = ${student6.age}")
    student6.printInfo()
  }

}

class Student2{
  var name: String = _
  var age: Int = _

}

class Student3(var name: String, var age: Int)

//主构造器参数无修饰
class Student4(name: String, age: Int){
  def printInfo(): Unit ={
    println(s"studnet4: name = ${name}, age = ${age}")
  }
}

class Student5(val name: String, val age: Int)  //常量

class Student6(var name: String, var age: Int){
  var school: String = _
  def this(name: String, age: Int, school: String){
    this(name, age)
    this.school = school
  }

  def printInfo(): Unit ={
    println(s"studnet6: name = ${name}, age = ${age}, school = ${school}")
  }
}
  1. 单例对象
    1. 单例对象采用object关键字声明
    2. 单例对象对应的类称之为伴生类,伴生对象的名称应该和伴生类名一致
    3. 单例对象中的属性和方法都可以通过伴生对象名(类名)直接调用访问
object Test18 {
  def main(args: Array[String]): Unit = {
    /*val student = new Student18("张三", 19)
    student.printInfo()*/
    val student = Student18.newStudent("张三", 20)
    student.printInfo()

    val student1 = Student18.apply("张三", 20)
    student1.printInfo()

    val student2 = Student18("张三", 21)  //调用伴生对象的 apply(底层优化) 方法(简写)
    student2.printInfo()
  }
}

class Student18 private (val name: String, val age: Int){      //private 主构造器私有化
  def printInfo(): Unit ={
    println(s"studnet6: name = ${name}, age = ${age}, school = ${Student18.school}")
  }
}

object Student18{
  val school: String = "FDB"

  //定义一个类的对象实例的创建方法
  def newStudent(name: String, age: Int): Student18 = new Student18(name, age)

  def apply(name: String, age: Int): Student18 = new Student18(name, age)
}
特质(Trait)
  1. Scala语言中,采用特质(trait)来代替接口的概念,也就是说,多个类具有相同的特质(特征)时,就可以将这个特质(特征)独立出来,采用关键字trait声明。
  2. Scala中的trait中即可以有抽象属性和方法,也可以有具体属性和方法,,一个类可以混入多个特质,,类似于java中的抽象类。
  3. Scala引入trait特征,第一个可以代替java的接口,第二个也是对单继承机制的一种补充。
  4. 基本语法:
    1. 没有父类:class 类名 extends 特质1 with 特质2
    2. 有父类:class 类名 extends 父类 with 特质1 with 特质2
	//动态混入(特质)
    val studentWithTalent = new Student21 with Talent {
      override def singing(): Unit = println("student is good at singing")
      override def dancing(): Unit = println("student is good at dancing")
    }
  1. 特质和抽象类的区别
    1. 优先使用特质,一个类扩展多个特质是很方便的,但却只能扩展一个抽象类
    2. 如果你需要构造函数参数,使用抽象类,因为抽象类可以定义带参数的构造函数,而特质不行(有无参构造)
  2. 类型检查和转换
    1. obj.isInstanceOf[T] :判断obj是不是T类型
    2. obj.asInstanceOf[T] :将obj强转成T类型
    3. classOf :获取对象的类名
  3. 自身类型
/**
 * 自身类型
 */
object Test_TraitSelfType {

  def main(args: Array[String]): Unit = {
    val user = new RegisterUser("张三", "122131")
    user.insert()
  }
}

class User(val name: String, val password: String)

trait UserDao {
  //类似于依赖注入
  _: User =>

  def insert(): Unit = {
    println(s"insert into db: ${this.name} ")
  }
}

class RegisterUser(name: String, password: String) extends User(name, password) with UserDao
  1. 枚举类和应用类
    1. 枚举类:继承Enumeration
    2. 应用类:继承App
集合
  1. Scala的集合有三大类,所有集合都扩展自Iterable特质
    1. 序列Seq
    2. 集Set
    3. 映射Map
  2. Scala都同时提供了可变和不可变版本
    1. 不可变集合:scala.collection.immutable,类似java中的String对象
      在这里插入图片描述

    2. 可变集合:scala.collection.mutable,类似StringBuilder
      在这里插入图片描述

    3. 建议:在操作集合的时候,不可变用符号,可变用方法

数组
  1. 不可变数组
    1. 定义:val arr1 = new Arry[Int] (10);val arr2 = Array(1,2,3,4)(调用伴生对象的apply方法)
    2. new 是关键字
    3. [Int]是指定可以存放的数据类型,如果希望存放任意数据类型,则指定Any
    4. (10),表示数组的大小,确定后就不可以变化
object Test01_ImmutableArray {
  def main(args: Array[String]): Unit = {
    val arr: Array[Int] = new Array[Int](5)
    arr(0) = 112
    arr(3) = 142
    for (i <- arr){
      println(i)
    }

    val arr2 = Array(1,2,3,4)
    arr2(1) = 10
    println("*********************")
    arr2.foreach(println)

    println("-----------------------")
    for(i <- 0 until arr2.length){
      println(arr2(i))
    }
    println("-----------------------")
    for (i <- arr2.indices){
      println(arr2(i))
    }

    println("-----------------------")
    for (i <- arr2){
      println(i)
    }

    val iterator = arr2.iterator
    while (iterator.hasNext){
      println(iterator.next())
    }

    println("-----------------------foreach")
    arr2.foreach(println)

    println("-----------------------")
    //不可变数组添加元素(底层创建一个新数组),添加到末尾
    val ints = arr2.:+(5)
    ints.foreach(println)

    println("-----------------------")
    val ints1 = arr2.+:(5)
    ints1.foreach(println)

    println("-----------------------")
    //ints1.:+(6) 简化
    val ints2 = ints1 :+ 6   //添加到末尾
    ints2.foreach(println)

    val ints3 = 7 +: ints2   //添加到头部
  }
}
  1. 可变数组
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer

object Test_ArrayBuffer {
  def main(args: Array[String]): Unit = {
    val arr: ArrayBuffer[Int] = new ArrayBuffer[Int]()
    //添加元素
    val newArr = arr :+ 1  //针对不可变数组
    println(arr == newArr)

    val newArr1 = arr += 1  //可变数组,引用赋值
    println(arr)
    println(newArr1)
    println(arr == newArr1)

    newArr1 += 2
    println(newArr1)
    println(arr)

    3 +=: arr   //从前面添加
    println(arr)
    arr.append(4)
    arr.prepend(5)
    arr.insert(1, 6)
    println(arr)

    arr.remove(5)  //按照索引删除
    println(arr)

    arr -= 1   //删除指定元素
    println(arr)

    //可变数组转换为不可变数组
    val array: ArrayBuffer[Int] = ArrayBuffer(11, 22, 33)
    val newArray: Array[Int] = array.toArray
    println(newArray.mkString(", "))
    println(array)

    //不可变数组转换成可变数组
    val buffer: mutable.Buffer[Int] = newArray.toBuffer
    println(buffer)
    println(newArray)
  }
}
  1. 二维数组
object Test_MulArray {
  def main(args: Array[String]): Unit = {
    //创建二维数组
    val array1: Array[Array[Int]] = Array.ofDim[Int](2, 3)

    array1(0)(2) = 1
    array1(1)(0) = 2

    for (i <- 0 until array1.length; j <- 0 until array1(i).length){
      println(array1(i)(j))
    }

    for (i <- array1.indices; j <- array1(i).indices){
      print(array1(i)(j) + "\t")
      if (j == array1(i).length -1) println()
    }

    array1.foreach(line => line.foreach(println))

    array1.foreach(_.foreach(println))
  }
}
列表(list)
  1. 不可变列表
object Test04_List {
  def main(args: Array[String]): Unit = {
    val list = List(1, 3, 3)
    println(list)

    println(list(1))

    list.foreach(println)

    val list2 = 10 +: list
    val list3 = list :+ 20
    println("-----------------------")
    list2.foreach(println)
    println("-----------------------")
    list3.foreach(println)

    val list4 = list.::(88)
    println(list4)

    println("-----------------------")
    val list5 = Nil.::(20)
    println(list5)

    val list6 = 10 :: 20 :: 30 :: 40 :: Nil
    println(list6)

    val list7 = list :: list6    //将list直接追加到list6头部
    println(list7)

    val list8 = list ::: list6   //将list中元素拆分后追加到list6头部
    println(list8)

    val list9 = list ++ list6   //将list中元素拆分后追加到list6头部
    println(list9)
  }
}
// 输出结果:
List(1, 3, 3)
3
1
3
3
-----------------------
10
1
3
3
-----------------------
1
3
3
20
List(88, 1, 3, 3)
-----------------------
List(20)
List(10, 20, 30, 40)
List(List(1, 3, 3), 10, 20, 30, 40)
List(1, 3, 3, 10, 20, 30, 40)
List(1, 3, 3, 10, 20, 30, 40)
  1. 可变列表
import scala.collection.mutable.ListBuffer

object Test05_ListBuffer {
  def main(args: Array[String]): Unit = {
    val list1: ListBuffer[Int] = new ListBuffer[Int]()
    val list2 = ListBuffer(1, 2, 3)

    println(list1)
    println(list2)

    //添加元素
    list1.append(12, 4, 5)
    list2.prepend(10)

    list1.insert(1, 9)
    println(list1)
    println(list2)

    88 +=: list1 += 99
    println(list1)

    val list3 = list1 ++ list2
    println(list3)

    list1 ++=: list2  // ++=
    println(list1)
    println(list2)

    list2(3) = 7
    println(list2)

    list2.remove(2)

    list2 -= 99

    println(list2)
  }
}
集合(set)
  1. 不可变集合
object Test06_ImmutableSet {
  def main(args: Array[String]): Unit = {
    val set1 = Set(1, 2, 3, 3)
    println(set1)

    //添加元素
    val set2 =  set1 + 20
    println(set1)
    println(set2)

    //合并set
    val set3 = Set(12, 55, 3, 88)
    val set4 = set1 ++ set3
    println(set4)

    //删除元素
    val set5 = set3 - 12
    println(set3)
    println(set5)
  }
}
  1. 可变集合
object Test07_MutableSet {
  def main(args: Array[String]): Unit = {
    //可变集合
    val set1: mutable.Set[Int] = mutable.Set[Int](1, 2, 3)
    println(set1)

    //添加元素
    val set2 = set1 + 20
    println(set1)
    println(set2)

    set1 += 30
    println(set1)

    set1.add(77)
    println(set1)

    //删除元素
    set1 -= 77
    println(set1)

    set1.remove(3)
    println(set1)

    println("------------------------")
    val set3 = mutable.Set(7, 8, 9)
    set1 ++= set3
    println(set1)
    println(set3)
  }
}
Map集合
  1. 不可变Map
object Test08_ImmutableMap {
  def main(args: Array[String]): Unit = {
    val map1: Map[String, Int] = Map("a" -> 1, "b" -> 2, "c" ->3)
    println(map1)
    println(map1.getClass)

    map1.foreach(println)
    map1.foreach((kv: (String, Int)) => println(kv))

    println(map1.get("a").get)
    println(map1.getOrElse("d", 0))
    println(map1("a"))
  }
  1. 可变Map
object Test09_MutableMap {
  def main(args: Array[String]): Unit = {
    val map1: mutable.Map[String, Int] = mutable.Map("a" -> 1, "b" -> 2, "c" -> 3)
    println(map1)
    println(map1.getClass)

    map1.put("d", 4)
    println(map1)

    map1 += (("e", 5))
    println(map1)

    //删除
    map1.remove("a")
    println(map1.getOrElse("a", 0))

    map1 -= "b"
    println(map1)

    map1.update("a", 100)
    map1.update("b", 200)
    println(map1)

    val map2: Map[String, Int] = Map("aa" -> 1, "bb" -> 2, "c" -> 300)
    map1 ++= map2
    println(map1)
    println(map2)
  }
}
元组
  1. 元组也是可以理解为一个容器,可以存放各种相同或不同类型的数据,说的简单点,就是将多个无关的数据封装为一个整体,称为元组。(元组中最大只能有22个元素)
object Test10_Tuple {
  def main(args: Array[String]): Unit = {
    val tuple: (String, Int, Char, Boolean) = ("hello", 1, 'a', true)
    println(tuple)
    println(tuple._1)
    println(tuple.productElement(1))
    println("------------------------")
    for (elem <- tuple.productIterator){
      println(elem)
    }

    //嵌套元组
    val mulTuple = (12, 0.3, "hello", (23, "scala"), 29)
    println(mulTuple._4._2)

  }
高级计算函数
  1. Map类(转换/映射)
object Test11_HightLevelFunction_Map {
  def main(args: Array[String]): Unit = {
    val list = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
    //1.过滤
    //选取偶数
    val evenList = list.filter((elem: Int) => {elem % 2 == 0})
    println(evenList)
    //奇数
    println(list.filter(_ % 2 == 1))

    //map
    println(list.map(_ * 2))
    println(list.map(x => x * x))

    //扁平化
    val nestedList: List[List[Int]] = List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9))

    val flatList = nestedList(0) ::: nestedList(1) ::: nestedList(2)
    println(flatList)

    val flatList2 = nestedList.flatten
    println(flatList2)

    //扁平映射
    //将一组字符串进行分词,并保存成单词的列表
    val strings: List[String] = List("hello world", "hello sacla", "hello java", "we study")
    val splitList: List[Array[String]] = strings.map(_.split(" ")) //分词
    val flattenList = splitList.flatten  // 打散扁平化

    println(flattenList)

    val flatmapList = strings.flatMap(_.split(" "))
    println(flatmapList)

    //分组groupBy
    //分成奇偶两组
    val groupMap: Map[Int, List[Int]] = list.groupBy(_ % 2)

    val groupMap2: Map[String, List[Int]] = list.groupBy(data => if (data % 2 == 0) "偶数" else "奇数")

    println(groupMap)
    println(groupMap2)

    //给定一组词汇,按照单词的首字母进行分组
    val wordList = List("china", "america", "alice", "canada", "cary", "bob", "japan")
    println(wordList.groupBy(_.charAt(0)))
  }
}
  1. Reduce类(把集合内的所有数据归约聚合到一个结果)
object Test12_HightLevelFunction_Reduce {
  def main(args: Array[String]): Unit = {
    val list = List(1, 2, 3, 4)

    //1. reduce
    println(list.reduce(_ + _))
    println(list.reduceLeft(_ + _))
    println(list.reduceRight(_ + _))

    val list2 = List(3, 4, 5, 8, 10)

    println(list2.reduce(_ - _))
    println(list2.reduceLeft(_ - _))
    println(list2.reduceRight(_ - _))

    //2.fold(带初始值)
    println(list.fold(10)(_ + _))   // 10 + 1 + 2 + 3 + 4
    println(list.foldLeft(10)(_ - _))  // 10 - 1 - 2 - 3 - 4
    println(list2.foldRight(11)(_ - _))  // 3 - (4 - (5 - (8 - (10 - 11))))

  }
}
  1. 合并Map
object Test_MergeMap {
  def main(args: Array[String]): Unit = {
    val map1 = Map("a" -> 1, "b"-> 3, "c" -> 6)
    val map2 = mutable.Map("a" -> 6, "b"-> 2, "c" -> 9, "d" -> 3)

    println(map1 ++ map2)

    val map3 = map1.foldLeft(map2)(
      (mergedMap, kv) =>{
        val key = kv._1
        val value = kv._2
        mergedMap(key) = mergedMap.getOrElse(key, 0) + value
        mergedMap
      }
    )
    println(map3)
  }
}
  1. WordCount(一)
object Test13_CommonWordCount {
  def main(args: Array[String]): Unit = {
    val stringList: List[String] = List(
      "hello",
      "hello world",
      "hello scala",
      "hello spark from scala",
      "hello flink from scala"
    )
    //1. 对字符串进行切分
    /*val wordList1: List[Array[String]] = stringList.map(_.split(" "))
    val wordList2: List[String] = wordList1.flatten
    println(wordList2)*/

    val wordList: List[String] = stringList.flatMap(_.split(" "))
    println(wordList)

    //分组
    val groupMap: Map[String, List[String]] = wordList.groupBy(word => word)
    println(groupMap)

    val countMap: Map[String, Int] = groupMap.map(kv => (kv._1, kv._2.length))

    //排序
    val sortList: List[(String, Int)] = countMap.toList.sortWith(_._2 > _._2).take(3)
    println(sortList)
  }
}
  1. WordCount(二)
object Test14_ComplexWordCount {
  def main(args: Array[String]): Unit = {
    val tupleList: List[(String, Int)] = List(
      ("hello", 1),
      ("hello world", 2),
      ("hello scala", 3),
      ("hello spark from scala", 1),
      ("hello flink from scala", 2)
    )

    //思路一
    val newStringList: List[String] = tupleList.map(kv => {
      (kv._1.trim + " ") * kv._2
    })
    println(newStringList)

    val wordCountList: List[(String, Int)] = newStringList.flatMap(_.split(" "))  //空格分词
      .groupBy(word => word)                                                              //分组
      .map(kv => (kv._1, kv._2.length))                                                   //统计单词个数
      .toList                                                                             //map 转 List((), ())
      .sortBy(_._2)(Ordering[Int].reverse)                                                //排序
      .take(3)                                                                            //左边取前三

    println(wordCountList)

    //思路二
    val preCountList: List[(String, Int)] = tupleList.flatMap(
      tuple =>{
        val strings: Array[String] = tuple._1.split(" ")
        strings.map(word => (word, tuple._2))
      }
    )
    println(preCountList)

    //分组
    val preCountMap: Map[String, List[(String, Int)]] = preCountList.groupBy(_._1)
    println(preCountMap)

    //叠加每个单词预统计的数值
    val countMap: Map[String, Int] = preCountMap.mapValues(
      tupleList => tupleList.map(_._2).sum
    )
    println(countMap)

    val countList: List[(String, Int)] = countMap.toList.sortWith(_._2 > _._2).take(3)
    println(countList)
  }
}
队列
import scala.collection.immutable.Queue
import scala.collection.mutable

object Test15_Queue {
  def main(args: Array[String]): Unit = {
    //可变队列
    val queue: mutable.Queue[String] = new mutable.Queue[String]()
    queue.enqueue("a", "b", "c", "d")
    println(queue)

    println(queue.dequeue())
    println(queue)
    println(queue.dequeue())
    println(queue)

    queue.enqueue("e", "f")
    println(queue)

    println(queue.dequeue())
    println(queue)

    println("----------------------------")
    //不可变
    val queue2: Queue[String] = Queue("a", "b", "c")
    val queue3 = queue2.enqueue("d")
    println(queue2)
    println(queue3)
  }
}
并行执行
import scala.collection.immutable
import scala.collection.parallel.immutable.ParSeq

object Test16_Parallel {
  def main(args: Array[String]): Unit = {
    val result: immutable.IndexedSeq[Long] = (1 to 100).map(
      x => Thread.currentThread.getId
    )
    println(result)

    //并行执行(par)
    val result2: ParSeq[Long] = (1 to 100).par.map(
      x => Thread.currentThread.getId
    )
    println(result2)
  }
}
模式匹配
object Test01_PatternMatchBase {
  def main(args: Array[String]): Unit = {
    //基本定义语法
    val x: Int = 2
    val y: String = x match {
      case 1 => "one"
      case 2 => "two"
      case 3 => "three"
      case _ => "other"
    }
    println(y)

    //用模式匹配实现简单的二元运算
    val a = 12
    val b = 13

    def matchDualOp(op: Char): Int = op match {
      case '+' => a + b
      case '-' => a - b
      case '*' => a * b
      case '/' => a / b
      case '%' => a % b
      case _ => -1
    }

    println(matchDualOp('+'))
    println(matchDualOp('\\'))

    //模式守卫
    //求一个整数的绝对值
    def abs(num: Int): Int = {
      num match {
        case i if i >= 0 => i
        case i if i < 0 => -i
      }
    }

    println(abs(1))
    println(abs(0))
    println(abs(-8))
  }
}

object Test02_MatchTypes {
  def main(args: Array[String]): Unit = {
    //匹配常量
    def describeConst(x: Any): String = x match {
      case 1 => "Int one"
      case "hello" => "String hello"
      case true => "Boolean true"
      case '+' => "Char +"
      case _ => ""
    }

    println(describeConst("hello"))

    //匹配类型
    def describeType(x: Any): String = x match {
      case i: Int => "Int " + i
      case s: String => "String " + s
      case list: List[String] => "List " + list
      case array: Array[Int] => "Array[Int] " + array.mkString(",")
      case a => "Something else: " + a
    }

    println(describeType(1))
    println(describeType(List("a", "b")))  //泛型擦除
    println(describeType(List(1, 2)))
    println(describeType(Array("2", "21")))  //Array 不存在泛型擦除

    //匹配数组
    for (arr <- List(
      Array(0),
      Array(1, 0),
      Array(0, 1, 0),
      Array(1, 1, 0),
      Array(2, 3, 7, 15),
      Array("hello", 20, 30)
    )) {
      val result = arr match {
        case Array(0) => "0"
        case Array(1, 0) => "Array(1, 0)"
        case Array(x, y) => "Array: " + x + "," + y
        case Array(0, _*) => "以0开头的数组"
        case Array(x, 1, z) => "中间为1的三元素数组"
        case _ => "something else"
      }
      println(result)
    }

    println("******************************")
    //匹配列表
    for (list <- List(
      List(0),
      List(1, 0),
      List(0, 0, 0),
      List(1, 1, 0),
      List(88),
      List("hello")
    )) {
      val result = list match {
        case List(0) => "0"
        case List(x, y) => "List(x, y)" + x + ", " + y
        case List(0, _*) => "List(0, ...)"
        case List(a) => "List(a): " + a
        case _ => "something else"
      }
      println(result)
    }

    //方式二
    val list = List(1, 2, 5, 7, 24)

    list match {
      case first :: second :: rest => println(s"first: $first, second: $second, rest: $rest")
      case _ => println("something else")
    }

    //匹配元组
    for (tuple <- List(
      (0, 1),
      (0, 0),
      (0, 1, 0),
      (0, 1, 1),
      (1, 23, 56),
      ("hello", true, 0.5)
    )) {
      val result = tuple match {
        case (a, b) => "" + a + ", " + b
        case (0, _) => "(0, _)"
        case (a, 1, _) => "(a, 1, _):" + a
        case (x, y, z) => "(x, y, z): " + x + " " + y + " " + z
        case _ => "something else"
      }
      println(result)
    }
  }
}

object Test03_MatchTupleExtend {
  def main(args: Array[String]): Unit = {
    //变量声明时匹配
    val (x, y) = (10, "hello")
    println(s"x: $x, y: $y")

    val List(first, second, _*) = List(23, 15, 9, 78)
    println(s"first: $first, second: $second")

    val fir :: sec :: rest = List(23, 15, 9, 78)
    println(s"fir: $fir, sec: $sec, rest: $rest")

    // for 推导式中进行模式匹配
    val list: List[(String, Int)] = List(("a", 12), ("b", 35), ("c", 27), ("a", 17))
    for (elem <- list) {
      println(elem._1 + " " + elem._2)
    }
    for ((word, count) <- list) {
      println(word + " " + count)
    }
    //只遍历key或者value
    for ((word, _) <- list) {
      println(word)
    }
    //指定某个位置的值
    for (("a", count) <- list) {
      println(count)
    }
  }
}

object Test04_MatchObject {
  def main(args: Array[String]): Unit = {
    val student = new Student("alice", 18)
    //针对对象实例内容进行匹配
    val result = student match {
      case Student("alice", 18) => "Alice 18"
      case _ => "else"
    }

    println(result)
  }
}

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

object Student{
  def apply(name: String, age: Int): Student = new Student(name, age)
  //实现unapply方法, 用来对对象属性进行拆解
  def unapply(student: Student): Option[(String, Int)] = {
    if (student == null) {
      None
    }else {
      Some((student.name, student.age))
    }
  }
}

object Test05_MatchCaseClass {
  def main(args: Array[String]): Unit = {
    val student = Student1("alice", 18)
    //针对对象实例内容进行匹配
    val result = student match {
      case Student1("alice", 18) => "Alice 18"
      case _ => "else"
    }

    println(result)
  }
}

//样例类
case class Student1(name: String, age: Int)

object Test06_PartialFunction {
  def main(args: Array[String]): Unit = {
    val list: List[(String, Int)] = List(("a", 12), ("b", 35), ("c", 27), ("a", 17))

    val newList = list.map(tuple => (tuple._1, tuple._2 * 2))

    val newList2 = list.map(
      tuple => {
        tuple match {
          case (word, count) => (word, count * 2)
        }
      }
    )

    //省略lambda表达式, 简化(偏函数)
    val newList3 = list.map {
      case (word, count) => (word, count * 2)
    }

    println(newList)
    println(newList2)
    println(newList3)

    val positiveAbs: PartialFunction[Int, Int] = {
      case x if x > 0 => x
    }
    val negativeAbs: PartialFunction[Int, Int] = {
      case x if x < 0 => -x
    }
    val zeroAbs: PartialFunction[Int, Int] = {
      case 0 => 0
    }

    def abs(x: Int): Int = (positiveAbs orElse negativeAbs orElse zeroAbs)(x)

    println(abs(-1))
    println(abs(1))
    println(abs(0))
  }
}

//异常处理
object Test01_Exception {
  def main(args: Array[String]): Unit = {
    try{
      val n = 10 / 0
    }catch {
      case e: ArithmeticException => {
        println("发送算数异常")
      }
      case e: Exception => {
        println("发生一般异常")
      }
    }finally {
      println("处理结束")
    }
  }
}
隐式转换(implicit)
  1. 当编译器第一次编译失败的时候,会在当前环境中查找能让代码编译通过的方法,用于将类型进行转换,实现二次编译。
  2. 隐式函数::隐式转换可以在不需改任何代码的情况下,扩展某个类的功能
  3. 隐式参数:普通方法或者函数中的参数可以通过implicit关键字声明为隐式参数,调用改方法时,就可以传入改参数,编译器会在相应的作用域寻找符合条件的隐式值
    1. 同一个作用域中,相同类型的隐式值只能有一个
    2. 编译器按照隐式参数的类型去寻找对应类型的隐式值,与隐式值的名称无关
    3. 隐式参数优先于默认参数
  4. 隐式类:其所带的有参构造参数有且只能有一个,隐式类必须定义在"类"或"伴生对象"或"包对象"里,即隐式类不能是顶级的
  5. 隐式解析机制:首先会在当前代码作用域下查找隐式实体(隐式方法,隐式类,隐式对象),如果查找失败,会继续在隐式参数的类型的作用域里查找,类型的作用域是指与该类型相关联的全部伴生对象,以及该类型所在包的包对象。
object Test02_Implicit {
  def main(args: Array[String]): Unit = {
    //隐式函数
    implicit def convert(num: Int): MyRichInt = new MyRichInt(num)
    //必须在当前作用域内
    println(10.myMax(15))

    //隐式类
    implicit class MyRichInt2(val self: Int) {
      def myMax2(n: Int): Int = if(n < self) self else n
      def myMin2(n: Int): Int = if(n < self) n else self
    }
    println(10.myMin2(9))

    //隐式参数(柯里化表达),根据类型查找,同一作用域范围内,一个类型的隐式参数只能有一个
    implicit val str: String = "张三"
    implicit val num: Int = 18
    def sayHello()(implicit name: String): Unit = {
      println("hello, " + name)
    }
    def sayHi(implicit name: String): Unit = {
      println("hi, " + name)
    }
    sayHello
    sayHi

    //简写
    def hiAge(): Unit = {
      println("hi, " + implicitly[Int])
    }
    hiAge
  }
}

class MyRichInt(val self: Int) {
  def myMax(n: Int): Int = if(n < self) self else n
  def myMin(n: Int): Int = if(n < self) n else self
}
泛型
  1. 协变:Son是Father的子类,则MyList[Son]也作为MyList[Father]的子类
  2. 逆变:Son是Father的子类,则MyList[Son]作为MyList[Father]的父类
  3. 不变:Son是Father的子类,则MyList[Son]与MyList[Father]无父子关系
object Test03_Generics {
  def main(args: Array[String]): Unit = {
    //1.协变和逆变
    //val childList: MyCollection[Parent] = new MyCollection[Child]        //[+E]
    val childList: MyCollection[SubChild] = new MyCollection[Child]        //[-E]

    /**
     * 上下限
     * [T <: Person]: 泛型上限
     * [T >: Person]: 泛型下限
     * 上下文限定:
     *  def f[A : B](a: A) = println(a) 等同于 def f[A](a: A)(implicit arg: B[A]) = println(a)
     * @param a
     * @tparam A
     */
    def test[A <: Child](a: A): Unit = {
      println(a.getClass.getName)
    }
    test[Child](new SubChild)
  }
}

//定义继承关系
class Parent {}
class Child extends Parent {}
class SubChild extends Child {}

/**
 * 定义带泛型的集合类型
 * [+E]: 协变
 * [-E]: 逆变
 * @tparam E
 */
class MyCollection[-E] {}

完结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值