240508Scala笔记

作者 : admin 本文共51918个字,预计阅读时间需要130分钟 发布时间: 2024-06-5 共3人阅读

240508Scala笔记

Scala概述:

SCala是Java的拓展,在Java的基础上又拓展了一些语法,例如: 输出Hello World

    println("HelloWorld")
    System.out.println("Hello Scala from Java")

上面两段代码都可以输出内容.

package chapter01
​
/*
    object: 关键字,声明一个单例对象
*/
object HelloWorld {
    
/*
    main 方法: 从外部可以直接调用执行的方法
    def 方法名称(参数名称:参数类型):返回值类型 = {方法体}
*/
  def main(args: Array[String]): Unit = {
    println("HelloWorld")
    System.out.println("Hello Scala from Java")
  }
}

其中上面的object是一个单例对象.

object : 关键字,声明一个单例对象

main 方法:从外部可以直接调用执行的方法

def 方法名称(参数名称:参数类型) : 返回值类型={方法体}

Scala入门:

(下面是一段java代码)创建一个学生类:(对方法的引用)

Java代码:

import scala.io.StdIn;

public class Student {
    private String name;
    private  Integer age;
    private  static  String school= "YelloRiwer";

    public Student(String name,Integer 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 alice = new Student("alice",20);
        Student bob = new Student("bob",23);
        alice.printInfo();
        bob.printInfo();
    }
}

运行结果:

alice 20 YelloRiwer
bob 23 YelloRiwer

如果我想要静态且不想要他的属性那就需要Scala. 下面这段Scala代码和上面的Java代码一样,但是比Java代码简洁了许多:

Scala代码:

package chapter01

class Student(name : String,age:Int) {
      def printInfo():Unit = {
        println(name+" "+age+" "+Student.school)
      }
}
//引入伴生对象
object Student{
      val school:String = "YelloRiwer"

  def main(args: Array[String]): Unit = {
    val alice = new Student("alice",20)
    val bob = new Student("bob",23)

    alice.printInfo()
    bob.printInfo()
  }
}

运行结果:

alice 20 YelloRiwer
bob 23 YelloRiwer

Scala基本操作:

IDEA快捷键: 快速格式化: Ctrl + Alt + L

2.2变量和常量(重点)

常量:在程序执行的过程中,其值不会被改变的变量

0)回顾:Java 变量和常量语法

变量类型 变量名称 = 初始值 
int a = 10

final 常量类型 常量名称 = 初始值 
final int b = 20

1)Scala基本语法

var 变量名 [: 变量类型] = 初始值 	
var i:Int = 10

val 常量名 [: 常量类型] = 初始值 
val j:Int = 20

注意:能用常量的地方不用变量


chapter02

Text02
变量与常量
package chapter02

import chapter01.Student

object Test02_Variable {
  def main(args: Array[String]): Unit = {
    // 声明一个变量的通用语法
    var a: Int = 10

    //(1)声明变量时,类型可以省略,编译器自动推导,即类型推导
    var a1 = 10
    val b1 = 23

    //(2)类型确定后,就不能修改,说明Scala是强数据类型语言。
    var a2 = 15    // a2类型为Int
//    a2 = "hello"

    //(3)变量声明时,必须要有初始值
//    var a3: Int

    //(4)在声明/定义一个变量时,可以使用var或者val来修饰,var修饰的变量可改变,val修饰的变量不可改。
    a1 = 12
//    b1 = 25

    var alice = new Student("alice", 20)
    alice = new Student("Alice", 20)
    alice = null
    val bob = new Student("bob", 23)
    bob.age = 24
    bob.printInfo()
//    bob = new Student("bob", 24)
  }
}

Text03
标识符
package chapter02

object Test03_Identifier {
  def main(args: Array[String]): Unit = {
    //(1)以字母或者下划线开头,后接字母、数字、下划线
    val hello: String = ""
    var Hello123 = ""
    val _abc = 123

//    val h-b = ""
//    val 123abc = 234

    //(2)以操作符开头,且只包含操作符(+ - * / # !等)
    val -+/% = "hello"
    println(-+/%)

    //(3)用反引号`....`包括的任意字符串,即使是Scala关键字(39个)也可以
    val `if` = "if"
    println(`if`)
  }
}

Text04
字符串拼接
package chapter02

object Test04_String {
  def main(args: Array[String]): Unit = {
    //(1)字符串,通过+号连接
    val name: String = "alice"
    val age: Int = 18
    println(age + "岁的" + name + "在尚硅谷学习")

    // *用于将一个字符串复制多次并拼接
    println(name * 3)

    //(2)printf用法:字符串,通过%传值。
    printf("%d岁的%s在尚硅谷学习", age, name)
    println()

    //(3)字符串模板(插值字符串):通过$获取变量值
    println(s"${age}岁的${name}在尚硅谷学习")

    val num: Double = 2.3456
    println(f"The num is ${num}%2.2f")    // 格式化模板字符串
    println(raw"The num is ${num}%2.2f")

    // 三引号表示字符串,保持多行字符串的原格式输出
    val sql = s"""
       |select *
       |from
       |  student
       |where
       |  name = ${name}
       |and
       |  age > ${age}
       |""".stripMargin
    println(sql)
  }
}

println() printf() System.out.println()

上面三个都可以输出内容

println和System.out.println一样

printf(“%d岁的%s在尚硅谷学习”, age, name)

println(s””)#字符串模板

println(f””)#快速格式化字符串

println(raw””)#原始格式输出

Text05
键盘输入
package chapter02

import scala.io.StdIn

object Test05_StdIn {
  def main(args: Array[String]): Unit = {
    // 输入信息
    println("请输入您的大名:")
    val name: String = StdIn.readLine()
    println("请输入您的芳龄:")
    val age: Int = StdIn.readInt()

    // 控制台打印输出
    println(s"欢迎${age}岁的${name}来到尚硅谷学习")
  }
}

Text06
读写文件
package chapter02

import java.io.{File, PrintWriter}
import scala.io.Source

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

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

Text07
文件类型
package chapter02

import chapter01.Student

object Test07_DataType {
  def main(args: Array[String]): Unit = {
    // 1. 整数类型
    val a1: Byte = 127
    val a2: Byte = -128

//    val a2: Byte = 128    // error

    val a3 = 12    // 整数默认类型为Int
    val a4: Long = 1324135436436L    // 长整型数值定义

    val b1: Byte = 10
    val b2: Byte = 10 + 20
    println(b2)

//    val b3: Byte = b1 + 20
    val b3: Byte = (b1 + 20).toByte
    println(b3)

    // 2. 浮点类型
    val f1: Float = 1.2345f
    val d1 = 34.2245

    // 3. 字符类型
    val c1: Char = 'a'
    println(c1)

    val c2: Char = '9'
    println(c2)

    // 控制字符
    val c3: Char = '	'    // 制表符
    val c4: Char = '
'    // 换行符
    println("abc" + c3 + "def")
    println("abc" + c4 + "def")

    // 转义字符
    val c5 = '\'    // 表示\自身
    val c6 = '\"'    // 表示"
    println("abc" + c5 + "def")
    println("abc" + c6 + "def")

    // 字符变量底层保存ASCII码
    val i1: Int = c1
    println("i1: " + i1)
    val i2: Int = c2
    println("i2: " + i2)

    val c7: Char = (i1 + 1).toChar
    println(c7)
    val c8: Char = (i2 - 1).toChar
    println(c8)

    // 4. 布尔类型
    val isTrue: Boolean = true
    println(isTrue)

    // 5. 空类型
    // 5.1 空值Unit
    def m1(): Unit = {
      println("m1被调用执行")
    }

    val a: Unit = m1()
    println("a: " + a)

    // 5.2 空引用Null
//    val n: Int = null    // error
    var student: Student = new Student("alice", 20)
    student = null
    println(student)

    // 5.3 Nothing
    def m2(n: Int): Int = {
      if (n == 0)
        throw new NullPointerException
      else
        return n
    }


    val b: Int = m2(2)
    println("b: " + b)
  }
}

Text08
自动类型转换:
package chapter02

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

    // 1. 自动类型转换
    //    (1)自动提升原则:有多种类型的数据混合运算时,系统首先自动将所有数据转换成精度大的那种数据类型,然后再进行计算。
    val a1: Byte = 10
    val b1: Long = 2353
    val result1: Long = a1 + b1
    val result11: Int = (a1 + b1.toInt) // 强转

    //    (2)把精度大的数值类型赋值给精度小的数值类型时,就会报错,反之就会进行自动类型转换。
    val a2: Byte = 10
    val b2: Int = a2
    //    val c2: Byte = b2    // error

    //    (3)(byte,short)和char之间不会相互自动转换。
    val a3: Byte = 10
    val b3: Char = 'b'
    //    val c3: Byte = b3    // error
    val c3: Int = b3
    println(c3)

    //    (4)byte,short,char他们三者可以计算,在计算时首先转换为int类型。
    val a4: Byte = 12
    val b4: Short = 25
    val c4: Char = 'c'
    val result4: Int = a4 + b4
    val result44: Int = a4 + b4 + c4
    println(result44)

    // 2. 强制类型转换
    //    (1)将数据由高精度转换为低精度,就需要使用到强制转换
    val n1: Int = -2.9.toInt
    println("n1: " + n1)

    //    (2)强转符号只针对于最近的操作数有效,往往会使用小括号提升优先级
    val n2: Int = 2.6.toInt + 3.7.toInt
    val n3: Int = (2.6 + 3.7).toInt
    println("n2: " + n2)
    println("n3: " + n3)

    // 3. 数值类型和String类型的转换
    // (1) 数值转String
    val n: Int = 27
    val s: String = n + ""
    println(s)

    // (2) String转数值
    val m: Int = "12".toInt
    val f: Float = "12.3".toFloat
    val f2: Int = "12.3".toDouble.toInt
    println(f2)
  }
}

Text09

package chapter02

/*
128: Int类型,占据4个字节,32位
原码 0000 0000 0000 0000 0000 0000 1000 0000
补码 0000 0000 0000 0000 0000 0000 1000 0000

截取最后一个字节,Byte
得到补码 1000 0000
表示最大负数 -128

130: Int类型,占据4个字节,32位
原码 0000 0000 0000 0000 0000 0000 1000 0010
补码 0000 0000 0000 0000 0000 0000 1000 0010

截取最后一个字节,Byte
得到补码 1000 0010
对应原码 1111 1110
-126
 */

object Test09_Problem_DataTypeConversion {
  def main(args: Array[String]): Unit = {
    var n: Int = 130
    val b: Byte = n.toByte
    println(b)
  }
}

范围数据循环(Until)

1)基本语法

for(i <- 1 until 3) {

 print(i + " ")

}

println()

(1)这种方式和前面的区别在于 i 是从 1 到 3-1

(2)即使前闭合后开的范围

2)案例实操

需求:输出 5 句 “宋宋,告别海狗人参丸吧”

object TestFor {
    
 def main(args: Array[String]): Unit = {
     
 for(i <- 1 until 5 + 1){
     
 println("宋宋,告别海狗人参丸吧" + i)
     
		 }
	 }
}

循环守卫

1)基本语法

for(i <- 1 to 3 if i != 2) {

 print(i + " ")

}

println()

说明:

(1)循环守卫,即循环保护式(也称条件判断式,守卫)。保护式为 true 则进入循环

体内部,为 false 则跳过,类似于 continue。

(2)与上面的代码等价

for (i <- 1 to 3){

if (i != 2) {

print(i + " ")

	}	

}

2)案例实操

需求:输出 1 到 5 中,不等于 3 的值

object TestFor {

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

 for (i <- 1 to 5 if i != 3) {

 println(i + "宋宋")

		 }

	 }

}

循环步长

1)基本语法

for (i <- 1 to 10 by 2) {

 println("i=" + i)

}

说明:by 表示步长

2)案例实操

需求:输出 1 到 10 以内的所有奇数 by表示步长

for (i <- 1 to 10 by 2) {

 println("i=" + i)

}

输出结果

i=1

i=3

i=5

i=7

i=9

嵌套循环

1)基本语法

for(i <- 1 to 3; j <- 1 to 3) {

 println(" i =" + i + " j = " + j)

}

说明:没有关键字,所以范围后一定要加;来隔断逻辑

2)基本语法

上面的代码等价

for (i <- 1 to 3) {

 for (j <- 1 to 3) {

 println("i =" + i + " j=" + j)

 	}

}

引入变量

1)基本语法

for(i <- 1 to 3; j = 4 - i) {

 println("i=" + i + " j=" + j)

}

说明:

(1)for 推导式一行中有多个表达式时,所以要加 ; 来隔断逻辑

(2)for 推导式有一个不成文的约定:当 for 推导式仅包含单一表达式时使用圆括号,

当包含多个表达式时,一般每行一个表达式,并用花括号代替圆括号,如下

for {

 i <- 1 to 3

j = 4 - i

} {

 println("i=" + i + " j=" + j)

}

2)案例实操

上面的代码等价于

for (i <- 1 to 3) {

 var j = 4 - i

 println("i=" + i + " j=" + j)

}

循环返回值

1)基本语法

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

println(res)

说明:将遍历过程中处理的结果返回到一个新 Vector 集合中,使用 yield 关键字。

注意:开发中很少使用。

2)案例实操

需求:将原数据中所有值乘以 2,并把数据返回到一个新的集合中。

object TestFor {

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

 var res = for(i <-1 to 10) yield {

 i * 2

	 }

 println(res)

	 }

}

输出结果:

Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)

倒序打印
1)说明:如果想倒序打印一组数据,可以用 reverse。
2)案例实操:
需求:倒序打印 10 到 1
for(i <- 1 to 10 reverse){
 println(i)
}

While和do…While循环控制

While和do…While的使用和Java语言中用法相同

While循环控制

1)基本语法

	循环变量初始化;
while (循环条件) {

 循环体(语句)

 循环变量迭代

}

说明:

(1)循环条件是返回一个布尔值的表达式

(2)while 循环是先判断再执行语句

(3)与 for 语句不同,while 语句没有返回值,即整个 while 语句的结果是 Unit 类型()

(4)因为 while 中没有返回值,所以当要用该语句来计算并返回结果时,就不可避免

的使用变量,而变量需要声明在 while 循环的外部,那么就等同于循环的内部对外部的变量

造成了影响,所以不推荐使用,而是推荐使用 for 循环。

2)案例实操

需求:输出 10 句 “宋宋,喜欢海狗人参丸”

object TestWhile {
 
 def main(args: Array[String]): Unit = {
 var i = 0
 while (i < 10) {
 println("宋宋,喜欢海狗人参丸" + i)
 i += 1
		 }
	 }
}

do…while循环控制

1)基本语法

 循环变量初始化;
do{
    循环体(语句)
 循环变量迭代
 } while(循环条件)

说明

(1)循环条件是返回一个布尔值的表达式

(2)do..while 循环是先执行,再判断

2)案例实操

需求:输出 10 句 “宋宋,喜欢海狗人参丸”

object TestWhile {
 def main(args: Array[String]): Unit = {
 var i = 0
 do {
 println("宋宋,喜欢海狗人参丸" + i)
 i += 1
		 } while (i < 10)
	 }
}

循环中断

1)基本说明

Scala 内置控制结构特地去掉了 break continue,是为了更好的适应函数式编程,推

荐使用函数式的风格解决break和continue的功能,而不是一个关键字。Scala中使用breakable

控制结构来实现 break 和 continue 功能。

2)案例实操

需求 1:采用异常的方式退出循环

def main(args: Array[String]): Unit = {
 
    try {
 		for (elem 
 }
 println("正常结束循环")
}

需求 2:采用 Scala 自带的函数,退出循环

import scala.util.control.Breaks
def main(args: Array[String]): Unit = {
	 Breaks.breakable(
		 for (elem <- 1 to 10) {
			 println(elem)
			 if (elem == 5) Breaks.break()
			 }
		 )
	 println("正常结束循环")
}

需求 3:对 break 进行省略

import scala.util.control.Breaks._
object TestBreak {
 def main(args: Array[String]): Unit = {
 
	 breakable {
		 for (elem <- 1 to 10) {
			 println(elem)
 			if (elem == 5) break
		 }
	 }
 
 println("正常结束循环")
 	}
}

需求 4:循环遍历 10 以内的所有数据,奇数打印,偶数跳过(continue)

object TestBreak {
 	def main(args: Array[String]): Unit = {
		 for (elem <- 1 to 10) {
 			if (elem % 2 == 1) {
				 println(elem)
			 } else {
				 println("continue")
			 }
		 }
	 }
}

多重循环

1)基本说明

(1)将一个循环放在另一个循环体内,就形成了嵌套循环。其中,for,while,do…while

均可以作为外层循环和内层循环。【建议一般使用两层,最多不要超过 3

(2)设外层循环次数为 m 次,内层为 n 次,则内层循环体实际上需要执行 m*n 次。

2)案例实操

需求:打印出九九乘法表

object TestWhile {
 	def main(args: Array[String]): Unit = {
 		for (i <- 1 to 9) {
			 for (j <- 1 to i) {
				 print(j + "*" + i + "=" + (i * j) + "	")
			 }
			 println()
		 }
	 }
}

输出结果:

240508Scala笔记插图

240511Scala笔记

第5章 函数式编程

5.1函数式编程

函数式编程:

1)面向对象编程

解决问题,分解对象,行为,属性,然后通过对象的关系以及行为的调用来解决问题。

对象:用户

行为:登录、连接 JDBC、读取数据库

属性:用户名、密码

Scala 语言是一个完全面向对象编程语言。万物皆对象

对象的本质:对数据和行为的一个封装

2)函数式编程

解决问题时,将问题分解成一个一个的步骤,将每个步骤进行封装(函数),通过调用

这些封装好的步骤,解决问题。

例如:请求->用户名、密码->连接 JDBC->读取数据库

Scala 语言是一个完全函数式编程语言。万物皆函数。

函数的本质:函数可以当做一个值进行传递

3)在 Scala 中函数式编程和面向对象编程完美融合在一起了。

5.1 函数基础

5.1.1 函数基本语法

1)基本语法

240508Scala笔记插图

2)案例实操

需求:定义一个函数,实现将传入的名称打印出来。

object TestFunction {
	def main(args: Array[String]): Unit = {
		 // (1)函数定义
 		def f(arg: String): Unit = {
     		 println(arg)
		 }
		 // (2)函数调用
		 // 函数名(参数)
		 f("hello world")
 	}
}

5.1.2 函数和方法的区别

1)核心概念

(1)为完成某一功能的程序语句的集合,称为函数。

(2)类中的函数称之方法。

2)案例实操

(1)Scala 语言可以在任何的语法结构中声明任何的语法

(2)函数没有重载和重写的概念;方法可以进行重载和重写

(3)Scala 中函数可以嵌套定义

object TestFunction {
 	// (2)方法可以进行重载和重写,程序可以执行
 	def main(): Unit = {
 	}
 	def main(args: Array[String]): Unit = {
 		// (1)Scala 语言可以在任何的语法结构中声明任何的语法
 		import java.util.Date
 		new Date()
 		// (2)函数没有重载和重写的概念,程序报错
 		def test(): Unit ={
 			println("无参,无返回值")
 		}
 		test()
 		def test(name:String):Unit={
	 		println()
	 	}
 
        //(3)Scala 中函数可以嵌套定义
 		def test2(): Unit ={
      	def test3(name:String):Unit={
			 println("函数可以嵌套定义")
			 }
 		}
	 }
}

5.1.3 函数定义

1)函数定义

(1)函数 1:无参,无返回值

(2)函数 2:无参,有返回值

(3)函数 3:有参,无返回值

(4)函数 4:有参,有返回值

(5)函数 5:多参,无返回值

(6)函数 6:多参,有返回值

2)案例实操

package chapter05

object Test02_FunctionDefine {
  def main(args: Array[String]): Unit = {
    //    (1)函数1:无参,无返回值
    def f1(): Unit = {
      println("1. 无参,无返回值")
    }
    f1()
    println(f1())

    println("=========================")

    //    (2)函数2:无参,有返回值
    def f2(): Int = {
      println("2. 无参,有返回值")
      return 12
    }
    println(f2())

    println("=========================")

    //    (3)函数3:有参,无返回值
    def f3(name: String): Unit = {
      println("3:有参,无返回值 " + name)
    }

    println(f3("alice"))

    println("=========================")

    //    (4)函数4:有参,有返回值
    def f4(name: String): String = {
      println("4:有参,有返回值 " + name)
      return "hi, " + name
    }

    println(f4("alice"))

    println("=========================")

    //    (5)函数5:多参,无返回值
    def f5(name1: String, name2: String): Unit = {
      println("5:多参,无返回值")
      println(s"${name1}和${name2}都是我的好朋友")
    }

    f5("alice","bob")

    println("=========================")

    //    (6)函数6:多参,有返回值
    def f6(a: Int, b: Int): Int = {
      println("6:多参,有返回值")
      return a + b
    }

    println(f6(12, 37))
  }
}

5.1.2.什么是面向对象,什么是面向过程?

面向对象:类似于盖浇饭,做到饭菜分离,可以通过组合不同的步骤

面向过程:类似于炒饭,都是把饭搅匀炒着吃,一气呵成

文心一言AI的说明:

面向对象和面向过程是两种不同的编程范式,它们在处理问题和设计程序时有着明显的区别。以下是它们之间的主要区别:

  1. 关注点

    • 面向过程:主要关注解决问题的步骤,即算法的实现。它将问题分解成一系列的函数或过程,并依次调用这些函数或过程来解决问题。

    • 面向对象:主要关注问题的本质,即对象及其之间的关系。它将问题分解成一系列的对象,并通过对象之间的交互来解决问题。

  2. 代码复用性

    • 面向过程:代码复用性较低。由于它主要关注解决问题的步骤,因此相同的代码段可能需要在不同的地方重复编写。

    • 面向对象:代码复用性较高。通过继承和组合等机制,可以轻松地重用已有的代码。

  3. 扩展性

    • 面向过程:扩展性较差。由于它主要关注具体的步骤实现,因此当需要添加新功能或修改现有功能时,可能需要修改大量的代码。

    • 面向对象:扩展性较好。由于它主要关注对象及其之间的关系,因此当需要添加新功能或修改现有功能时,通常只需要修改相应的对象即可。

  4. 抽象程度

    • 面向过程:抽象程度较低。它主要关注具体的步骤实现,因此代码中的细节较多。

    • 面向对象:抽象程度较高。它主要关注问题的本质和对象之间的关系,因此可以将问题抽象成更高级别的概念。

  5. 设计复杂性

    • 面向过程:设计复杂性较低。由于它主要关注具体的步骤实现,因此设计过程相对简单。

    • 面向对象:设计复杂性较高。由于它主要关注对象及其之间的关系,因此需要更多的思考和设计来确保对象之间的交互和协作能够正确地实现。

  6. 适用场景

    • 面向过程:适用于简单的问题或算法实现,以及需要高效率的场景(如底层开发、游戏开发等)。

    • 面向对象:适用于复杂的问题或系统,需要高抽象性和可扩展性的场景(如大型软件开发、企业级应用等)。

总的来说,面向对象和面向过程各有优缺点,适用于不同的场景和需求。在选择使用哪种编程范式时,需要根据具体情况进行权衡和选择。


5.1.3.什么是函数式编程

函数式编程是一种编程范式,主要思想是将计算机运算看作函数的计算。它强调程序的执行结果而非执行过程,通过一系列嵌套的函数调用来实现运算过程。函数式编程中,函数是“第一等公民”,它们可以与变量一样,被赋值给其他变量,作为参数传入函数,或者作为其他函数的返回值。

函数式编程的主要特性包括:

  1. 闭包和高阶函数:函数式编程支持函数作为第一类对象,这些函数可以像对象一样被操作。高阶函数则是指可以接受其他函数作为参数或返回函数的函数。

  2. 惰性计算:在惰性计算中,表达式不是在绑定到变量时立即计算,而是在需要其值时进行计算。这允许编写可能产生无穷输出的函数,而无需担心内存溢出问题。

  3. 递归:函数式编程经常使用递归作为控制流程的机制,尤其是在处理列表或树形结构时。

  4. 无副作用:函数式编程中的函数不应产生除运算结果以外的其他影响,即函数的运行不应依赖于或改变外部状态。

  5. 不可变性:在函数式编程中,变量通常是不可变的,即它们的值在初始化后不能被修改。如果需要改变值,通常会创建一个新的变量。

  6. 引用透明:函数的运行应仅依赖于其输入参数,而与外部状态或变量无关。

函数式编程的例子包括LISP、Haskell、Clean、Erlang和Miranda等语言。这种编程范式在并发编程、数据处理和科学计算等领域具有广泛应用。


5.1.4 函数参数

1)案例实操

(1)可变参数

(2)如果参数列表中存在多个参数,那么可变参数一般放置在最后

(3)参数默认值,一般将有默认值的参数放置在参数列表的后面

(4)带名参数

package chapter05

object Test03_FunctionParameter {
  def main(args: Array[String]): Unit = {
    //    (1)可变参数
    def f1(str: String*): Unit = {
      println(str)
    }

    f1("alice")
    f1("aaa", "bbb", "ccc")

    //    (2)如果参数列表中存在多个参数,那么可变参数一般放置在最后
    def f2(str1: String, str2: String*): Unit = {
      println("str1: " + str1 + " str2: " + str2)
    }
    f2("alice")
    f2("aaa", "bbb", "ccc")

    //    (3)参数默认值,一般将有默认值的参数放置在参数列表的后面
    def f3(name: String = "atguigu"): Unit = {
      println("My school is " + name)
    }

    f3("school")
    f3()

    //    (4)带名参数
    def f4(name: String = "atguigu", age: Int): Unit = {
      println(s"${age}岁的${name}在尚硅谷学习")
    }

    f4("alice", 20)
    f4(age = 23, name = "bob")
    f4(age = 21)
  }
}
5.1.5 函数至简原则(重点)

函数至简原则:能省则省

1)至简原则细节

(1)return 可以省略,Scala 会使用函数体的最后一行代码作为返回值

(2)如果函数体只有一行代码,可以省略花括号

(3)返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)

(4)如果有 return,则不能省略返回值类型,必须指定

(5)如果函数明确声明 unit,那么即使函数体中使用 return 关键字也不起作用

(6)Scala 如果期望是无返回值类型,可以省略等号

(7)如果函数无参,但是声明了参数列表,那么调用时,小括号,可加可不加

(8)如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略

(9)如果不关心名称,只关心逻辑处理,那么函数名(def)可以省略

2)案例实操

package chapter05

// 函数至简原则
object Test04_Simplify {
  def main(args: Array[String]): Unit = {

    def f0(name: String): String = {
      return name
    }

    println(f0("atguigu"))

    println("==========================")

    //    (1)return可以省略,Scala会使用函数体的最后一行代码作为返回值
    def f1(name: String): String = {
      name
    }
    println(f1("atguigu"))

    println("==========================")

    //    (2)如果函数体只有一行代码,可以省略花括号
    def f2(name: String): String = name
    println(f2("atguigu"))

    println("==========================")

    //    (3)返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)
    def f3(name: String) = name
    println(f3("atguigu"))

    println("==========================")

    //    (4)如果有return,则不能省略返回值类型,必须指定
//    def f4(name: String) = {
//      return name
//    }
//
//    println(f4("atguigu"))

    println("==========================")

    //    (5)如果函数明确声明unit,那么即使函数体中使用return关键字也不起作用
    def f5(name: String): Unit = {
      return name
    }

    println(f5("atguigu"))

    println("==========================")

    //    (6)Scala如果期望是无返回值类型,可以省略等号
    def f6(name: String) {
      println(name)
    }

    println(f6("atguigu"))

    println("==========================")

    //    (7)如果函数无参,但是声明了参数列表,那么调用时,小括号,可加可不加
    def f7(): Unit = {
      println("atguigu")
    }

    f7()
    f7

    println("==========================")

    //    (8)如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略
    def f8: Unit = {
      println("atguigu")
    }

//    f8()
    f8

    println("==========================")

    //    (9)如果不关心名称,只关心逻辑处理,那么函数名(def)可以省略
    def f9(name: String): Unit = {
      println(name)
    }

    // 匿名函数,lambda表达式
    (name: String) => { println(name) }

    println("==========================")

  }
}
5.1.6匿名函数
package chapter05

object Test05_Lambda {
  def main(args: Array[String]): Unit = {
    val fun = (name: String) => {
      println(name)
    }
    fun("atguigu")

    println("========================")

    // 定义一个函数,以函数作为参数输入
    def f(func: String => Unit): Unit = {
      func("atguigu")
    }

    f(fun)
    f((name: String) => {
      println(name)
    })

    println("========================")

    // 匿名函数的简化原则
    //    (1)参数的类型可以省略,会根据形参进行自动的推导
    f((name) => {
      println(name)
    })

    //    (2)类型省略之后,发现只有一个参数,则圆括号可以省略;其他情况:没有参数和参数超过1的永远不能省略圆括号。
    f( name => {
      println(name)
    })

    //    (3)匿名函数如果只有一行,则大括号也可以省略
    f( name => println(name) )

    //    (4)如果参数只出现一次,则参数省略且后面参数可以用_代替
    f( println(_) )

    //     (5) 如果可以推断出,当前传入的println是一个函数体,而不是调用语句,可以直接省略下划线
    f( println )

    println("=========================")

    // 实际示例,定义一个”二元运算“函数,只操作1和2两个数,但是具体运算通过参数传入
    def dualFunctionOneAndTwo(fun: (Int, Int)=>Int): Int = {
      fun(1, 2)
    }

    val add = (a: Int, b: Int) => a + b
    val minus = (a: Int, b: Int) => a - b

    println(dualFunctionOneAndTwo(add))
    println(dualFunctionOneAndTwo(minus))

    // 匿名函数简化
    println(dualFunctionOneAndTwo((a: Int, b: Int) => a + b))
    println(dualFunctionOneAndTwo((a: Int, b: Int) => a - b))

    println(dualFunctionOneAndTwo((a, b) => a + b))
    println(dualFunctionOneAndTwo( _ + _))
    println(dualFunctionOneAndTwo( _ - _))

    println(dualFunctionOneAndTwo((a, b) => b - a))
    println(dualFunctionOneAndTwo( -_ + _))
  }
}

5.2 高级函数

5.2.1 高阶函数

函数的高阶用法:

package chapter05

object Test06_HighOrderFunction {
  def main(args: Array[String]): Unit = {
    def f(n: Int): Int = {
      println("f调用")
      n + 1
    }
    def fun(): Int = {
      println("fun调用")
      1
    }

    val result: Int = f(123)
    println(result)

    // 1. 函数作为值进行传递
    val f1: Int=>Int = f
    val f2 = f _

    println(f1)
    println(f1(12))
    println(f2)
    println(f2(35))

    val f3: ()=>Int = fun
    val f4 = fun _
    println(f3)
    println(f4)

    // 2. 函数作为参数进行传递
    // 定义二元计算函数
    def dualEval(op: (Int, Int)=>Int, a: Int, b: Int): Int = {
      op(a, b)
    }

    def add(a: Int, b: Int): Int = {
      a + b
    }

    println(dualEval(add, 12, 35))
    println(dualEval((a, b) => a + b, 12, 35))
    println(dualEval(_ + _, 12, 35))

    // 3. 函数作为函数的返回值返回
    def f5(): Int=>Unit = {
      def f6(a: Int): Unit = {
        println("f6调用 " + a)
      }
      f6    // 将函数直接返回
    }

//    val f6 = f5()
//    println(f6)
//    println(f6(25))

    println(f5()(25))
  }
}
5.2.2 高阶函数2

关于yield的使用

val array = Array(1, 2, 3, 4, 5)  
val squared = for (elem <- array) yield elem * elem // 平方每个元素  
  
// squared 现在是 Vector(1, 4, 9, 16, 25)  
println(squared)  
  
// 如果你想要一个List而不是Vector  
val squaredList = (for (elem <- array) yield elem * elem).toList  
println(squaredList) // List(1, 4, 9, 16, 25)

高阶函数(数组):

package chapter05

object Test07_Practice_CollectionOperation {
  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  el* 2)
    println(newArray2.mkString(", "))
  }
}
5.2.3 高阶函数练习
package chapter05

object Test08_Practice {
  def main(args: Array[String]): Unit = {
    // 1. 练习1
    val fun = (i: Int, s: String, c: Char) => {
      if (i == 0 && s == "" && c == '0') false else true
    }

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

    println("===========================")

    // 2. 练习2
    def func(i: Int): String=>(Char=>Boolean) = {
      def f1(s: String): Char=>Boolean = {
        def f2(c: Char): Boolean = {
          if (i == 0 && s == "" && c == '0') false else true
        }
        f2
      }
      f1
    }

    println(func(0)("")('0'))
    println(func(0)("")('1'))
    println(func(23)("")('0'))
    println(func(0)("hello")('0'))

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

    println(func1(0)("")('0'))
    println(func1(0)("")('1'))
    println(func1(23)("")('0'))
    println(func1(0)("hello")('0'))

    // 柯里化
    def func2(i: Int)(s: String)(c: Char): Boolean = {
      if (i == 0 && s == "" && c == '0') false else true
    }
    println(func2(0)("")('0'))
    println(func2(0)("")('1'))
    println(func2(23)("")('0'))
    println(func2(0)("hello")('0'))
  }
}
5.2.4 柯里化和闭包
package chapter05

object Test09_ClosureAndCurrying {
  def main(args: Array[String]): Unit = {
    def add(a: Int, b: Int): Int = {
      a + b
    }

    // 1. 考虑固定一个加数的场景
    def addByFour(b: Int): Int = {
      4 + b
    }

    // 2. 扩展固定加数改变的情况
    def addByFive(b: Int): Int = {
      5 + b
    }

    // 3. 将固定加数作为另一个参数传入,但是是作为”第一层参数“传入
    def addByFour1(): Int=>Int = {
      val a = 4
      def addB(b: Int): Int = {
        a + b
      }
      addB
    }

    def addByA(a: Int): Int=>Int = {
      def addB(b: Int): Int = {
        a + b
      }
      addB
    }

    println(addByA(35)(24))

    val addByFour2 = addByA(4)
    val addByFive2 = addByA(5)

    println(addByFour2(13))
    println(addByFive2(25))

    // 4. lambda表达式简写
    def addByA1(a: Int): Int=>Int = {
      (b: Int) => {
        a + b
      }
    }
    def addByA2(a: Int): Int=>Int = {
      b => a + b
    }

    def addByA3(a: Int): Int=>Int = a + _
    val addByFour3 = addByA3(4)
    val addByFive3 = addByA3(5)

    println(addByFour3(13))
    println(addByFive3(25))

    // 5. 柯里化
    def addCurrying(a: Int)(b: Int): Int = {
      a + b
    }

    println(addCurrying(35)(24))
  }
}
5.2.5 递归
package chapter05

import scala.annotation.tailrec

object Test10_Recursion {
  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 loop(n: Int, currRes: Int): Int = {
      if (n == 0) return currRes
      loop(n - 1, currRes * n)
    }
    loop(n, 1)
  }
}
5.2.6控制抽象
package chapter05

object Test11_ControlAbstraction {
  def main(args: Array[String]): Unit = {
    // 1. 传值参数
    def f0(a: Int): Unit = {
      println("a: " + a)
      println("a: " + a)
    }
    f0(23)

    def f1(): Int = {
      println("f1调用")
      12
    }
    f0(f1())

    println("========================")

    // 2. 传名参数,传递的不再是具体的值,而是代码块
    def f2(a: =>Int): Unit = {
      println("a: " + a)
      println("a: " + a)
    }

    f2(23)
    f2(f1())

    f2({
      println("这是一个代码块")
      29
    })

  }
}
2.控制抽象练习
package chapter05

object Test12_MyWhile {
  def main(args: Array[String]): Unit = {
    var n = 10

    // 1. 常规的while循环
    while (n >= 1){
      println(n)
      n -= 1
    }

    // 2. 用闭包实现一个函数,将代码块作为参数传入,递归调用
    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
    }

    // 3. 用匿名函数实现
    def myWhile2(condition: =>Boolean): (=>Unit)=>Unit = {
      // 内层函数需要递归调用,参数就是循环体
      op => {
        if (condition){
          op
          myWhile2(condition)(op)
        }
      }
    }
    println("=================")
    n = 10
    myWhile2(n >= 1){
      println(n)
      n -= 1
    }

    // 3. 用柯里化实现
    def myWhile3(condition: =>Boolean)(op: =>Unit): Unit = {
      if (condition){
        op
        myWhile3(condition)(op)
      }
    }

    println("=================")
    n = 10
    myWhile3(n >= 1){
      println(n)
      n -= 1
    }
  }
}
5.2.6 惰性函数(懒加载)
package chapter05

object Test13_Lazy {
  def main(args: Array[String]): Unit = {
    lazy val result: Int = sum(13, 47)

    println("1. 函数调用")
    println("2. result = " + result)
    println("4. result = " + result)
  }

  def sum(a: Int, b: Int): Int = {
    println("3. sum调用")
    a + b
  }
}

第6章 面向对象

6.1 scala类

6.1.1 包的命名
package com{

  import com.atguigu.scala.Inner

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

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

// 在同一文件中定义不同的包
package aaa{
  package bbb{

    object Test01_Package{
      def main(args: Array[String]): Unit = {
        import com.atguigu.scala.Inner
        println(Inner.in)
      }
    }
  }
}
6.1.2 包说明(包语句)
6.1.3 包对象
package object chapter06 {

 val commonValue = "Yello River"
  def commonMethod() = {
    println(s"我们在${commonValue}学习")
  }
}
6.1.4 导包说明

6.2 类和对象

6.2.1 定义类
package chapter06

import scala.beans.BeanProperty

object Test03_Class {
  def main(args: Array[String]): Unit = {
    // 创建一个对象
    val student = new Student()
//    student.name   // error, 不能访问private属性
    println(student.age)
    println(student.sex)
    student.sex = "female"
    println(student.sex)
  }
}

// 定义一个类
class Student {
  // 定义属性
  private var name: String = "alice"
  @BeanProperty
  var age: Int = _
  var sex: String = _
}
6.2.2 属性

6.3 封装


6.1.1 封装

Access:

package chapter06

object Test04_Access {
  def main(args: Array[String]): Unit = {
    // 创建对象
    val person: Person = new Person()
//    person.idCard    // error
//    person.name    // error
    println(person.age)
    println(person.sex)

    person.printInfo()

    var worker: Worker = new Worker()
//    worker = new Worker()
//    worker.age = 23
    worker.printInfo()
  }
}

// 定义一个子类
class Worker extends Person {
  override def printInfo(): Unit = {
//    println(idCard)    // error
    name = "bob"
    age = 25
    sex = "male"

    println(s"Worker: $name $sex $age")
  }
}

ClassForAccess:

package chapter06

object Test04_ClassForAccess {

}

// 定义一个父类
class Person {
  private var idCard: String = "3523566"
  protected var name: String = "alice"
  var sex: String = "female"
  private[chapter06] var age: Int = 18

  def printInfo(): Unit = {
    println(s"Person: $idCard $name $sex $age")
  }
}

class Worker extends Perison{} #里面的extends是继承的意思,Worker继承Persion

override def printInfo(): Unit = {} #里的override是重写的意思,重写printInfo方法

6.2.5 构造器

构造方法1:

package chapter06

object Test05_Constructor {
  def main(args: Array[String]): Unit = {
    val student1 = new Student1
    student1.Student1()

    val student2 = new Student1("alice")
    val student3 = new Student1("bob", 25)
  }
}

// 定义一个类
class Student1() {
  // 定义属性
  var name: String = _
  var age: Int = _

  println("1. 主构造方法被调用")

  // 声明辅助构造方法
  def this(name: String) {
    this()    // 直接调用主构造器
    println("2. 辅助构造方法一被调用")
    this.name = name
    println(s"name: $name age: $age")
  }

  def this(name: String, age: Int){
    this(name)
    println("3. 辅助构造方法二被调用")
    this.age = age
    println(s"name: $name age: $age")
  }

  def Student1(): Unit = {
    println("一般方法被调用")
  }
}

构造方法2:

package chapter06

object Test05_Constructor {
  def main(args: Array[String]): Unit = {
    val student1 = new Student1
    student1.Student1()

    val student2 = new Student1("alice")
    val student3 = new Student1("bob", 25)
  }
}

// 定义一个类
class Student1() {
  // 定义属性
  var name: String = _
  var age: Int = _

  println("1. 主构造方法被调用")

  // 声明辅助构造方法
  def this(name: String) {
    this()    // 直接调用主构造器
    println("2. 辅助构造方法一被调用")
    this.name = name
    println(s"name: $name age: $age")
  }

  def this(name: String, age: Int){
    this(name)
    println("3. 辅助构造方法二被调用")
    this.age = age
    println(s"name: $name age: $age")
  }

  def Student1(): Unit = {
    println("一般方法被调用")
  }
}

构造器1:

package chapter06

object Test06_ConstructorParams {
  def main(args: Array[String]): Unit = {
    val student2 = new Student2
    student2.name = "alice"
    student2.age = 18
    println(s"student2: name = ${student2.name}, age = ${student2.age}")

    val student3 = new Student3("bob", 20)
    println(s"student3: name = ${student3.name}, age = ${student3.age}")

    val student4 = new Student4("cary", 25)
//    println(s"student4: name = ${student4.name}, age = ${student4.age}")
    student4.printInfo()

    val student5 = new Student5("bob", 20)
    println(s"student3: name = ${student5.name}, age = ${student5.age}")

    student3.age = 21

    val student6 = new Student6("cary", 25, "atguigu")
    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(){
    println(s"student4: name = ${name}, age = $age")
  }
}

//class Student4(_name: String, _age: Int){
//  var name: String = _name
//  var age: Int = _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(){
    println(s"student6: name = ${name}, age = $age, school = $school")
  }
}
6.4.1 继承和多态

继承和多态1:

package chapter06

object Test07_Inherit {
  def main(args: Array[String]): Unit = {
    val student1: Student7 = new Student7("alice", 18)
    val student2 = new Student7("bob", 20, "std001")

    student1.printInfo()
    student2.printInfo()

    val teacher = new Teacher
    teacher.printInfo()

    def personInfo(person: Person7): Unit = {
      person.printInfo()
    }

    println("=========================")

    val person = new Person7
    personInfo(student1)
    personInfo(teacher)
    personInfo(person)
  }
}

// 定义一个父类
class Person7() {
  var name: String = _
  var age: Int = _

  println("1. 父类的主构造器调用")

  def this(name: String, age: Int){
    this()
    println("2. 父类的辅助构造器调用")
    this.name = name
    this.age = age
  }

  def printInfo(): Unit = {
    println(s"Person: $name $age")
  }
}

// 定义子类
class Student7(name: String, age: Int) extends Person7(name, age) {
  var stdNo: String = _

  println("3. 子类的主构造器调用")

  def this(name: String, age: Int, stdNo: String){
    this(name, age)
    println("4. 子类的辅助构造器调用")
    this.stdNo = stdNo
  }

  override def printInfo(): Unit = {
    println(s"Student: $name $age $stdNo")
  }
}

class Teacher extends Person7 {
  override def printInfo(): Unit = {
    println(s"Teacher")
  }
}

继承和多态2:

package chapter06

object Test08_DynamicBind {
  def main(args: Array[String]): Unit = {
    val student: Person8 = new Student8
    println(student.name)
    student.hello()
  }
}

class Person8 {
  val name: String = "person"
  def hello(): Unit = {
    println("hello person")
  }
}

class Student8 extends Person8 {
  override val name: String = "student"
  override def hello(): Unit = {
    println("hello student")
  }
}

6.5 抽象类

6.5.1 抽象属性和方法
package chapter06

object Test09_AbstractClass {
  def main(args: Array[String]): Unit = {
    val student = new Student9
    student.eat()
    student.sleep()
  }
}

// 定义抽象类
abstract class Person9{
  // 非抽象属性
  var name: String = "person"

  // 抽象属性
  var age: Int

  // 非抽象方法
  def eat(): Unit = {
    println("person eat")
  }

  // 抽象方法
  def sleep(): Unit
}

// 定义具体的实现子类
class Student9 extends Person9 {
  // 实现抽象属性和方法
  var age: Int = 18

  def sleep(): Unit = {
    println("student sleep")
  }

  // 重写非抽象属性和方法
//  override val name: String = "student"
  name = "student"

  override def eat(): Unit = {
    super.eat()
    println("student eat")
  }
}
6.5.2 匿名子类
package chapter06

object Test10_AnnoymousClass {
  def main(args: Array[String]): Unit = {
    val person: Person10 = new Person10 {
      override var name: String = "alice"

      override def eat(): Unit = println("person eat")
    }
    println(person.name)
    person.eat()
  }
}

// 定义抽象类
abstract class Person10 {
  var name: String
  def eat(): Unit
}

6.6 单例对象(伴生对象)

6.6.1 单例对象
package chapter06

object Test11_Object {
  def main(args: Array[String]): Unit = {
//    val student = new Student11("alice", 18)
//    student.printInfo()

    val student1 = Student11.newStudent("alice", 18)
    student1.printInfo()

    val student2 = Student11.apply("bob", 19)
    student2.printInfo()

    val student3 = Student11("bob", 19)
    student3.printInfo()
  }
}

// 定义类
class Student11 private(val name: String, val age: Int){
  def printInfo(){
    println(s"student: name = ${name}, age = $age, school = ${Student11.school}")
  }
}

// 伴生对象
object Student11{
  val school: String = "atguigu"

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

  def apply(name: String, age: Int): Student11 = new Student11(name, age)
}
6.2.2 单例设计模式
package chapter06

object Test12_Singleton {
  def main(args: Array[String]): Unit = {
    val student1 = Student12.getInstance()
    student1.printInfo()

    val student2 = Student12.getInstance()
    student2.printInfo()

    println(student1)
    println(student2)
  }
}

class Student12 private(val name: String, val age: Int){
  def printInfo(){
    println(s"student: name = ${name}, age = $age, school = ${Student11.school}")
  }
}

// 饿汉式
//object Student12 {
//  private val student: Student12 = new Student12("alice", 18)
//  def getInstance(): Student12 = student
//}

// 懒汉式
object Student12 {
  private var student: Student12 = _
  def getInstance(): Student12 = {
    if (student == null){
      // 如果没有对象实例的话,就创建一个
      student = new Student12("alice", 18)
    }
    student
  }
}
6.2.3 特质#Test13
package chapter06

object Test13_Trait {
  def main(args: Array[String]): Unit = {
    val student: Student13 = new Student13
    student.sayHello()
    student.study()
    student.dating()
    student.play()
  }
}

// 定义一个父类
class Person13 {
  val name: String = "person"
  var age: Int = 18
  def sayHello(): Unit = {
    println("hello from: " + name)
  }
  def increase(): Unit = {
    println("person increase")
  }
}

// 定义一个特质
trait Young {
  // 声明抽象和非抽象属性
  var age: Int
  val name: String = "young"

  // 声明抽象和非抽象的方法
  def play(): Unit = {
    println(s"young people $name is playing")
  }

  def dating(): Unit
}

class Student13 extends Person13 with Young {
  // 重写冲突的属性
  override val name: String = "student"

  // 实现抽象方法
  def dating(): Unit = println(s"student $name is dating")

  def study(): Unit = println(s"student $name is studying")

  // 重写父类方法
  override def sayHello(): Unit = {
    super.sayHello()
    println(s"hello from: student $name")
  }
}
6.2.4 特质的混入#Test14
package chapter06

object Test14_TraitMixin {
  def main(args: Array[String]): Unit = {
    val student = new Student14
    student.study()
    student.increase()

    student.play()
    student.increase()

    student.dating()
    student.increase()

    println("===========================")
    // 动态混入
    val studentWithTalent = new Student14 with Talent {
      override def dancing(): Unit = println("student is good at dancing")
      override def singing(): Unit = println("student is good at singing")
    }

    studentWithTalent.sayHello()
    studentWithTalent.play()
    studentWithTalent.study()
    studentWithTalent.dating()
    studentWithTalent.dancing()
    studentWithTalent.singing()
  }
}

// 再定义一个特质
trait Knowledge {
  var amount: Int = 0
  def increase(): Unit
}

trait Talent {
  def singing(): Unit
  def dancing(): Unit
}

class Student14 extends Person13 with Young with Knowledge {
  // 重写冲突的属性
  override val name: String = "student"

  // 实现抽象方法
  def dating(): Unit = println(s"student $name is dating")

  def study(): Unit = println(s"student $name is studying")

  // 重写父类方法
  override def sayHello(): Unit = {
    super.sayHello()
    println(s"hello from: student $name")
  }

  // 实现特质中的抽象方法
  override def increase(): Unit = {
    amount += 1
    println(s"student $name knowledge increased: $amount")
  }
}
6.2.5 #Test15
package chapter06

object Test15_TraitOverlying {
  def main(args: Array[String]): Unit = {
    val student = new Student15
    student.increase()

    //钻石问题特征叠加
    val myFootBall = new MyFootBall
    println(myFootBall.describe())

  }
}


trait  Knowledge15{
  var amount: Int = 0
  def increase():Unit ={
    println("knowledge increased")
  }
}
//定义球类特征
trait Ball{
    def describe():String = "ball"
}
trait  ColorBall extends Ball{
  var color : String = "red"
}

trait CategoryBall extends Ball{
  var category : String = "foot"

  override def describe(): String = category+"-"+super.describe()
}

//  定义一个自定义球的类
class MyFootBall extends CategoryBall with ColorBall{
  override def describe(): String = "my ball is a "+super[CategoryBall].describe()
}


trait Talent15{
  def singing():Unit
  def dancing():Unit

  def increase(): Unit = {
    println("talent increased")
  }
}

class Student15 extends Person13 with Talent15 with Knowledge15{
  override def dancing(): Unit = println("dancing")

  override def singing(): Unit = println("singing")

  override def increase(): Unit = {
    super[Person13].increase()

  }
}
6.2.6 #Test16
package chapter06

object Test16_TraitSelfType {
  def main(args: Array[String]): Unit = {
    val user = new RegisterUser("alice", "123456")
    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
6.2.7 #Test17_Textends
package chapter06

object Test17_Extends {
  def main(args: Array[String]): Unit = {
    // 1. 类型的检测和转换
    val student: Student17 = new Student17("alice", 18)
    student.study()
    student.sayHi()
    val person: Person17 = new Student17("bob", 20)
    person.sayHi()

    // 类型判断
    println("student is Student17: " + student.isInstanceOf[Student17])
    println("student is Person17: " + student.isInstanceOf[Person17])
    println("person is Person17: " + person.isInstanceOf[Person17])
    println("person is Student: " + person.isInstanceOf[Student17])

    val person2: Person17 = new Person17("cary", 35)
    println("person2 is Student17: " + person2.isInstanceOf[Student17])

    // 类型转换
    if (person.isInstanceOf[Student17]){
      val newStudent = person.asInstanceOf[Student17]
      newStudent.study()
    }

    println(classOf[Student17])

    // 2. 测试枚举类
    println(WorkDay.MONDAY)
  }
}

class Person17(val name: String, val age: Int){
  def sayHi(): Unit = {
    println("hi from person " + name)
  }
}

class Student17(name: String, age: Int) extends Person17(name, age){
  override def sayHi(): Unit = {
    println("hi from student " + name)
  }
  def study(): Unit = {
    println("student study")
  }
}

// 定义枚举类对象
object WorkDay extends Enumeration {
  val MONDAY = Value(1, "Monday")
  val TUESDAY = Value(2, "TuesDay")
}

// 定义应用类对象
object TestApp extends App {
  println("app start")

  type MyString = String
  val a: MyString = "abc"
  println(a)
}

240520Scala笔记

第 7 章 集合

7.1 集合1 数组Array

集合(Test01_ImmutableArray):

package chapter07

object Test01_ImmutableArray {
  def main(args: Array[String]): Unit = {
    // 1. 创建数组
    val arr: Array[Int] = new Array[Int](5)
    // 另一种创建方式
    val arr2 = Array(12, 37, 42, 58, 97)
    println(arr)

    // 2. 访问元素
    println(arr(0))
    println(arr(1))
    println(arr(4))
//    println(arr(5))

    arr(0) = 12
    arr(4) = 57
    println(arr(0))
    println(arr(1))
    println(arr(4))

    println("========================")

    // 3. 数组的遍历
    // 1) 普通for循环
    for (i <- 0 until arr.length){
      println(arr(i))
    }

    for (i <- arr.indices) println(arr(i))

    println("---------------------")

    // 2) 直接遍历所有元素,增强for循环
    for (elem  println(elem) )

    arr.foreach( println )

    println(arr2.mkString("--"))

    println("========================")
    // 4. 添加元素
    val newArr = arr2.:+(73)
    println(arr2.mkString("--"))
    println(newArr.mkString("--"))

    val newArr2 = newArr.+:(30)
    println(newArr2.mkString("--"))

    val newArr3 = newArr2 :+ 15
    val newArr4 = 19 +: 29 +: newArr3 :+ 26 :+ 73
    println(newArr4.mkString(", "))
  }
}

不可变数组用 +: 或 :+ 追加元素 可变数组用 arr1.append(6) 追加元素

7.2 集合2

package chapter07

import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer

object Test02_ArrayBuffer {
  def main(args: Array[String]): Unit = {
    // 1. 创建可变数组
    val arr1: ArrayBuffer[Int] = new ArrayBuffer[Int]()
    val arr2 = ArrayBuffer(23, 57, 92)

    println(arr1)
    println(arr2)

    // 2. 访问元素
//    println(arr1(0))     // error
    println(arr2(1))
    arr2(1) = 39
    println(arr2(1))

    println("======================")
    // 3. 添加元素
    val newArr1 = arr1 :+ 15
    println(arr1)
    println(newArr1)
    println(arr1 == newArr1)

    val newArr2 = arr1 += 19
    println(arr1)
    println(newArr2)
    println(arr1 == newArr2)
    newArr2 += 13
    println(arr1)

    77 +=: arr1
    println(arr1)
    println(newArr2)

    arr1.append(36)
    arr1.prepend(11, 76)
    arr1.insert(1, 13, 59)
    println(arr1)

    arr1.insertAll(2, newArr1)
    arr1.prependAll(newArr2)

    println(arr1)

    // 4. 删除元素
    arr1.remove(3)
    println(arr1)

    arr1.remove(0, 10)
    println(arr1)

    arr1 -= 13
    println(arr1)

    // 5. 可变数组转换为不可变数组
    val arr: ArrayBuffer[Int] = ArrayBuffer(23, 56, 98)
    val newArr: Array[Int] = arr.toArray
    println(newArr.mkString(", "))
    println(arr)

    // 6. 不可变数组转换为可变数组
    val buffer: mutable.Buffer[Int] = newArr.toBuffer
    println(buffer)
    println(newArr)
  }
}

arr.toArray 变成不可变数组 newArr.toBuffer 变成可变数组

7.3 集合3

package chapter07

object Test03_MulArray {
  def main(args: Array[String]): Unit = {
    // 1. 创建二维数组
    val array: Array[Array[Int]] = Array.ofDim[Int](2, 3)

    // 2. 访问元素
    array(0)(2) = 19
    array(1)(0) = 25

    println(array.mkString(", "))
    for (i <- 0 until array.length; j <- 0 until array(i).length){
      println(array(i)(j))
    }
    for (i <- array.indices; j  line.foreach(println))

    array.foreach(_.foreach(println))
  }
}

7.4 集合4 列表List

package chapter07

object Test04_List {
  def main(args: Array[String]): Unit = {
    // 1. 创建一个List
    val list1 = List(23, 65, 87)
    println(list1)

    // 2. 访问和遍历元素
    println(list1(1))
//    list1(1) = 12
    list1.foreach(println)

    // 3. 添加元素
    val list2 = 10 +: list1
    val list3 = list1 :+ 23
    println(list1)
    println(list2)
    println(list3)

    println("==================")

    val list4 = list2.::(51)
    println(list4)

    val list5 = Nil.::(13)
    println(list5)

    val list6 = 73 :: 32 :: Nil
    val list7 = 17 :: 28 :: 59 :: 16 :: Nil
    println(list7)

    // 4. 合并列表
    val list8 = list6 :: list7
    println(list8)

    val list9 = list6 ::: list7
    println(list9)

    val list10 = list6 ++ list7
    println(list10)

  }
}

7.5 集合5

package chapter07

import scala.collection.mutable.ListBuffer

object Test05_ListBuffer {
  def main(args: Array[String]): Unit = {
    // 1. 创建可变列表
    val list1: ListBuffer[Int] = new ListBuffer[Int]()
    val list2 = ListBuffer(12, 53, 75)

    println(list1)
    println(list2)

    println("==============")

    // 2. 添加元素
    list1.append(15, 62)
    list2.prepend(20)

    list1.insert(1, 19, 22)

    println(list1)
    println(list2)

    println("==============")

    31 +=: 96 +=: list1 += 25 += 11
    println(list1)

    println("==============")
    // 3. 合并list
    val list3 = list1 ++ list2
    println(list1)
    println(list2)

    println("==============")

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

    println("==============")

    // 4. 修改元素
    list2(3) = 30
    list2.update(0, 89)
    println(list2)

    // 5. 删除元素
    list2.remove(2)
    list2 -= 25
    println(list2)
  }
}

7.6 集合6 数集Set

package chapter07

object Test06_ImmutableSet {
  def main(args: Array[String]): Unit = {
    // 1. 创建set
    val set1 = Set(13, 23, 53, 12, 13, 23, 78)
    println(set1)

    println("==================")

    // 2. 添加元素
    val set2 = set1 + 129
    println(set1)
    println(set2)
    println("==================")

    // 3. 合并set
    val set3 = Set(19, 13, 23, 53, 67, 99)
    val set4 = set2 ++ set3
    println(set2)
    println(set3)
    println(set4)

    // 4. 删除元素
    val set5 = set3 - 13
    println(set3)
    println(set5)
  }
}

7.7 集合7

package chapter07

import scala.collection.mutable

object Test07_MutableSet {
  def main(args: Array[String]): Unit = {
    // 1. 创建set
    val set1: mutable.Set[Int] = mutable.Set(13, 23, 53, 12, 13, 23, 78)
    println(set1)

    println("==================")

    // 2. 添加元素
    val set2 = set1 + 11
    println(set1)
    println(set2)

    set1 += 11
    println(set1)

    val flag1 = set1.add(10)
    println(flag1)
    println(set1)
    val flag2 = set1.add(10)
    println(flag2)
    println(set1)

    println("==================")

    // 3. 删除元素
    set1 -= 11
    println(set1)

    val flag3 = set1.remove(10)
    println(flag3)
    println(set1)
    val flag4 = set1.remove(10)
    println(flag4)
    println(set1)

    println("==================")

    // 4. 合并两个Set
//    val set3 =
val set3 = Set(13, 12, 13, 27, 98)
    println(set1)
    println(set3)
    println("==================")
    set1 ++ set3
    val set4 = set1 ++ set3
    println(set1)
    println(set3)
    println(set4)
    println("==================")
    println(set1)
    println(set3)
    set1 ++= set3
    println(set1)
  }
}

7.8 集合8 映射(散列表)Map

package chapter07

object Test08_ImmutableMap {
  def main(args: Array[String]): Unit = {
    // 1. 创建map
    val map1: Map[String, Int] = Map("a" -> 13, "b" -> 25, "hello" -> 3)
    println(map1)
    println(map1.getClass)

    println("==========================")
    // 2. 遍历元素
    map1.foreach(println)
    map1.foreach( (kv: (String, Int)) => println(kv) )

    println("============================")

    // 3. 取map中所有的key 或者 value
    for (key  ${map1.get(key)}")
    }

    // 4. 访问某一个key的value
    println("a: " + map1.get("a").get)
    println("c: " + map1.get("c"))
    println("c: " + map1.getOrElse("c", 0))

    println(map1("a"))
  }
}

7.9 集合9

package chapter07

import scala.collection.mutable

object Test09_MutableMap {
  def main(args: Array[String]): Unit = {
    // 1. 创建map
    val map1: mutable.Map[String, Int] = mutable.Map("a" -> 13, "b" -> 25, "hello" -> 3)
    println(map1)
    println(map1.getClass)

    println("==========================")

    // 2. 添加元素
    map1.put("c", 5)
    map1.put("d", 9)
    println(map1)

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

    println("====================")

    // 3. 删除元素
    println(map1("c"))
    map1.remove("c")
    println(map1.getOrElse("c", 0))

    map1 -= "d"
    println(map1)

    println("====================")

    // 4. 修改元素
    map1.update("c", 5)
    map1.update("e", 10)
    println(map1)

    println("====================")

    // 5. 合并两个Map
    val map2: Map[String, Int] = Map("aaa" -> 11, "b" -> 29, "hello" -> 5)
//    map1 ++= map2
    println(map1)
    println(map2)

    println("---------------------------")
    val map3: Map[String, Int] = map2 ++ map1
    println(map1)
    println(map2)
    println(map3)
  }
}

7.10 集合10 元祖tuple

package chapter07

object Test10_Tuple {
  def main(args: Array[String]): Unit = {
    // 1. 创建元组
    val tuple: (String, Int, Char, Boolean) = ("hello", 100, 'a', true)
    println(tuple)

    // 2. 访问数据
    println(tuple._1)
    println(tuple._2)
    println(tuple._3)
    println(tuple._4)

    println(tuple.productElement(1))

    println("====================")
    // 3. 遍历元组数据
    for (elem <- tuple.productIterator)
      println(elem)

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

7.11 集合11 集合的常用函数

package chapter07

object Test11_CommonOp {
  def main(args: Array[String]): Unit = {
    val list = List(1,3,5,7,2,89)
    val set = Set(23,34,423,75)

    //    (1)获取集合长度
    println(list.length)

    //    (2)获取集合大小
    println(set.size)

    //    (3)循环遍历
    for (elem <- list)
      println(elem)

    set.foreach(println)

    //    (4)迭代器
    for (elem <- list.iterator) println(elem)

    println("====================")
    //    (5)生成字符串
    println(list)
    println(set)
    println(list.mkString("--"))

    //    (6)是否包含
    println(list.contains(23))
    println(set.contains(23))
  }
}

这个比较实用一点 !!!

7.12 集合12 衍生集合

package chapter07

object Test12_DerivedCollection {
  def main(args: Array[String]): Unit = {
    val list1 = List(1,3,5,7,2,89)
    val list2 = List(3,7,2,45,4,8,19)

    //    (1)获取集合的头
    println(list1.head)

    //    (2)获取集合的尾(不是头的就是尾)
    println(list1.tail)

    //    (3)集合最后一个数据
    println(list2.last)

    //    (4)集合初始数据(不包含最后一个)
    println(list2.init)

    //    (5)反转
    println(list1.reverse)

    //    (6)取前(后)n个元素
    println(list1.take(3))
    println(list1.takeRight(4))

    //    (7)去掉前(后)n个元素
    println(list1.drop(3))
    println(list1.dropRight(4))

    println("=========================")
    //    (8)并集
    val union = list1.union(list2)
    println("union: " + union)
    println(list1 ::: list2)

    // 如果是set做并集,会去重
    val set1 = Set(1,3,5,7,2,89)
    val set2 = Set(3,7,2,45,4,8,19)

    val union2 = set1.union(set2)
    println("union2: " + union2)
    println(set1 ++ set2)

    println("-----------------------")
    //    (9)交集
    val intersection = list1.intersect(list2)
    println("intersection: " + intersection)

    println("-----------------------")
    //    (10)差集
    val diff1 = list1.diff(list2)
    val diff2 = list2.diff(list1)
    println("diff1: " + diff1)
    println("diff2: " + diff2)

    println("-----------------------")
    //    (11)拉链
    println("zip: " + list1.zip(list2))
    println("zip: " + list2.zip(list1))

    println("-----------------------")
    //    (12)滑窗
    for (elem <- list1.sliding(3))
      println(elem)
    println("-----------------------")

    for (elem <- list2.sliding(4, 2))
      println(elem)

    println("-----------------------")
    for (elem <- list2.sliding(3, 3))
      println(elem)
  }
}

7.13 集合13 集合计算简单函数(sum求和…)

package chapter07

object Test13_SimpleFunction {
  def main(args: Array[String]): Unit = {
    val list = List(5,1,8,2,-3,4)
    val list2 = List(("a", 5), ("b", 1), ("c", 8), ("d", 2), ("e", -3), ("f", 4))

    //    (1)求和
    var sum = 0
    for (elem  tuple._2 ))
    println(list2.maxBy( _._2 ))

    //    (4)最小值
    println(list.min)
    println(list2.minBy(_._2))

    println("========================")

    //    (5)排序
    // 5.1 sorted
    val sortedList = list.sorted
    println(sortedList)

    // 从大到小逆序排序
    println(list.sorted.reverse)
    // 传入隐式参数
    println(list.sorted(Ordering[Int].reverse))

    println(list2.sorted)

    // 5.2 sortBy
    println(list2.sortBy(_._2))
    println(list2.sortBy(_._2)(Ordering[Int].reverse))

    // 5.3 sortWith
    println(list.sortWith( (a: Int, b: Int) => {a < b} ))
    println(list.sortWith( _  _))
  }
}

7.14 集合14 集合计算高级函数(过滤…)

package chapter07

object Test14_HighLevelFunction_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 ))

    println("=======================")

    // 2. 映射map
    // 把集合中每个数乘2
    println(list.map(_ * 2))
    println(list.map( x => x * x))

    println("=======================")

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

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

    val flatList2 = nestedList.flatten
    println(flatList2)

    println("=======================")

    // 4. 扁平映射
    // 将一组字符串进行分词,并保存成单词的列表
    val strings: List[String] = List("hello world", "hello scala", "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)

    println("========================")

    // 5. 分组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) ) )
  }
}

7.15 集合15 redeuc归约,fold折叠

package chapter07

object Test15_HighLevelFunction_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(_ + _))

    println("===========================")

    val list2 = List(3,4,5,8,10)
    println(list2.reduce(_ - _))    // -24
    println(list2.reduceLeft(_ - _))
    println(list2.reduceRight(_ - _))    // 3 - (4 - (5 - (8 - 10))), 6

    println("===========================")
    // 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)))),  -5
  }
}

7.16 集合16 合并列表(如果有相同的key就把value值相加)

package chapter07

import scala.collection.mutable

object Test16_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)
  }
}

7.17 集合17

package chapter07

object Test17_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 = stringList.flatMap(_.split(" "))
    println(wordList)

    // 2. 相同的单词进行分组
    val groupMap: Map[String, List[String]] = wordList.groupBy(word => word)
    println(groupMap)

    // 3. 对分组之后的list取长度,得到每个单词的个数
    val countMap: Map[String, Int] = groupMap.map(kv => (kv._1, kv._2.length))

    // 4. 将map转换为list,并排序取前3
    val sortList: List[(String, Int)] = countMap.toList
      .sortWith( _._2 > _._2 )
      .take(3)

    println(sortList)
  }
}

7.18 集合18

package chapter07

object Test18_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.size) )     // 统计出每个单词的个数
      .toList
      .sortBy(_._2)(Ordering[Int].reverse)
      .take(3)

    println(wordCountList)

    println("================================")

    // 思路二:直接基于预统计的结果进行转换
    // 1. 将字符串打散为单词,并结合对应的个数包装成二元组
    val preCountList: List[(String, Int)] = tupleList.flatMap(
      tuple => {
        val strings: Array[String] = tuple._1.split(" ")
        strings.map( word => (word, tuple._2) )
      }
    )
    println(preCountList)

    // 2. 对二元组按照单词进行分组
    val preCountMap: Map[String, List[(String, Int)]] = preCountList.groupBy( _._1 )
    println(preCountMap)

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

    // 4. 转换成list,排序取前3
    val countList = countMap.toList
      .sortWith(_._2 > _._2)
      .take(3)
    println(countList)
  }
}

7.19 集合19

package chapter07

import scala.collection.immutable.Queue
import scala.collection.mutable
import scala.collection.parallel.immutable

object Test19_Queue {
  def main(args: Array[String]): Unit = {
    // 创建一个可变队列
    val queue: mutable.Queue[String] = new mutable.Queue[String]()

    queue.enqueue("a", "b", "c")

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

    queue.enqueue("d", "e")

    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)

  }
}

7.20 集合20

package chapter07

import scala.collection.immutable
import scala.collection.parallel.immutable.ParSeq

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

    val result2: ParSeq[Long] = (1 to 100).par.map(
      x => Thread.currentThread.getId
    )
    println(result2)
  }
}

第 8 章 模式匹配

8.1 模式匹配1

package chapter08

object Test01_PatternMatchBase {
  def main(args: Array[String]): Unit = {
    // 1. 基本定义语法
    val x: Int = 5
    val y: String = x match {
      case 1 => "one"
      case 2 => "two"
      case 3 => "three"
      case _ => "other"
    }
    println(y)

    // 2. 示例:用模式匹配实现简单二元运算
    val a = 25
    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('/'))
    println(matchDualOp('\'))

    println("=========================")

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

    println(abs(67))
    println(abs(0))
    println(abs(-24))
  }
}

8.2 模式匹配2

package chapter08

object Test02_MatchTypes {
  def main(args: Array[String]): Unit = {
    // 1. 匹配常量
    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"))
    println(describeConst('+'))
    println(describeConst(0.3))

    println("==================================")

    // 2. 匹配类型
    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(35))
    println(describeType("hello"))
    println(describeType(List("hi", "hello")))
    println(describeType(List(2, 23)))
    println(describeType(Array("hi", "hello")))
    println(describeType(Array(2, 23)))

    // 3. 匹配数组
    for (arr  "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("=========================")

    // 4. 匹配列表
    // 方式一
    for (list  "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 list1 = List(1, 2, 5, 7, 24)
    val list = List(24)

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


    println("===========================")
    // 5. 匹配元组
    for (tuple  "" + 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)
    }
  }
}

8.3 模式匹配3

package chapter08

object Test03_MatchTupleExtend {
  def main(args: Array[String]): Unit = {
    // 1. 在变量声明时匹配
    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"first: $fir, second: $sec, rest: $rest")

    println("=====================")

    // 2. for推导式中进行模式匹配
    val list: List[(String, Int)] = List(("a", 12), ("b", 35), ("c", 27), ("a", 13))

    // 2.1 原本的遍历方式
    for (elem <- list){
      println(elem._1 + " " + elem._2)
    }

    // 2.2 将List的元素直接定义为元组,对变量赋值
    for ((word, count) <- list ){
      println(word + ": " + count)
    }

    println("-----------------------")
    // 2.3 可以不考虑某个位置的变量,只遍历key或者value
    for ((word, _) <- list)
      println(word)

    println("-----------------------")

    // 2.4 可以指定某个位置的值必须是多少
    for (("a", count) <- list){
      println(count)
    }
  }
}

8.4 模式匹配4

package chapter08

object Test04_MatchObject {
  def main(args: Array[String]): Unit = {
    val student = new Student("alice", 19)

    // 针对对象实例的内容进行匹配
    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))
    }
  }
}

8.5 模式匹配5

package chapter08

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)

8.6 模式匹配6

package chapter08

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

    // 1. map转换,实现key不变,value2倍
    val newList = list.map( tuple => (tuple._1, tuple._2 * 2) )

    // 2. 用模式匹配对元组元素赋值,实现功能
    val newList2 = list.map(
      tuple => {
        tuple match {
          case (word, count) => (word, count * 2)
        }
      }
    )

    // 3. 省略lambda表达式的写法,进行简化
    val newList3 = list.map {
          case (word, count) => (word, count * 2)
      }

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

    // 偏函数的应用,求绝对值
    // 对输入数据分为不同的情形:正、负、0
    val positiveAbs: PartialFunction[Int, Int] = {
      case x if x > 0 => x
    }
    val negativeAbs: PartialFunction[Int, Int] = {
      case x if x  -x
    }
    val zeroAbs: PartialFunction[Int, Int] = {
      case 0 => 0
    }

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

    println(abs(-67))
    println(abs(35))
    println(abs(0))
  }
}

第 9 章 异常与泛型

9.1 异常

package chapter09plus

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("处理结束")
    }
  }
}

9.2 泛型 1

package chapter09plus

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

    val new12 = new MyRichInt(12)
    println(new12.myMax(15))

    // 1. 隐式函数
    implicit def convert(num: Int): MyRichInt = new MyRichInt(num)

    println(12.myMax(15))

    println("============================")

    // 2. 隐式类
    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(12.myMin2(15))

    println("============================")

    // 3. 隐式参数

    implicit val str: String = "alice"
//    implicit val str2: String = "alice2"
    implicit val num: Int = 18

    def sayHello()(implicit name: String): Unit = {
      println("hello, " + name)
    }
    def sayHi(implicit name: String = "atguigu"): 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
}

9.3 泛型 2

package chapter09plus

object Test03_Generics {
  def main(args: Array[String]): Unit = {
    // 1. 协变和逆变
    val child: Parent = new Child
//    val childList: MyCollection[Parent] = new MyCollection[Child]
    val childList: MyCollection[SubChild] = new MyCollection[Child]

    // 2. 上下限
    def test[A <: Child](a: A): Unit = {
      println(a.getClass.getName)
    }

    test[SubChild](new SubChild)
  }
}

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

// 定义带泛型的集合类型
class MyCollection[-E] {}
本站无任何商业行为
个人在线分享 » 240508Scala笔记
E-->