Scala教程

article/2025/10/14 14:03:00

1. 基础语法

Scala语言是基于Java虚拟机运行的,所以基本的语法和Java是没有区别的。但是为了简化Java的开发以及融合其他的编程语言的优点和特性,Scala在基本的语法上做了大量的修改和优化,让程序员开发起来更简单,方便,灵活。

1.1 变量

Scala声明变量有两种方式,一个用val,一个用var。

val / var 变量名 : 变量类型 = 变量值

val定义的值是不可变的,它不是一个常量,是不可变量,或称之为只读变量

1.2. 常用类型

Scala语言是完全面向对象的语言,所以并不区分基本类型和引用类型,这些类型都是对象,我们称之为常用类型。

Scala常用类型中包含有7种数值类型:Byte、Char、Short、Int、Long、Float、Double及Boolean类型,还有String类型。

Byte

8, 有符号

Char

16, 无符号

Short

16, 有符号

Int

32, 有符号

Long

64, 有符号

Double

64, 双精度浮点数

Boolean

true 或者 false

String

其实就是由Char数组组成

2. 控制结构

scala中的循环表达式分为3类:① to  ②  Range   ③ until  【底层实际上都是scala.collection.immutable.Range】

  • to : 前闭后闭
  • Range : 前闭后开, 可以使用步长,但是步长不能为0
  • until : 前闭后开
    println(1 to 10) //Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)println(Range(1, 10)) //Range(1, 2, 3, 4, 5, 6, 7, 8, 9)println(Range(1, 10, 2)) // Range(1, 3, 5, 7, 9)println(1 until 10) // Range(1, 2, 3, 4, 5, 6, 7, 8, 9)

2.1  if else表达式

//演示scala条件表达式
object IfScala extends App {val x = 0val resBoolean = if (x > 0) true else false //false// 0 > 0 不成立, 且代码没有 else 分支, res2 是什么呢val res2 = if (x > 0) 2 //()   相当于else ()// if ... else if ... else 代码较多时可以使用代码块{}val score = 78val res4 = {if (score > 60 && score < 70) "及格"else if (score >= 70 && score < 80) "良好" else "优秀"}println(res4)  //良好
}

注:

(1)Scala中任意表达式都是有返回值的,也就意味着if else表达式其实是有返回结果的,具体返回结果的值取决于满足条件的代码体的最后一行内容

    val a = 10val b = if (a>0) true else falseprint(b) // true

// ( ) => Unit => void

(2)如果大括号内的逻辑代码只有一行,大括号可以省略

    val a = 10if (a>0)print("a > 0")elseprint("a <= 0")

2.2 while表达式

Scala提供和Java一样的while和do循环,与If语句不同,While语句本身没有值,即整个While语句的结果是Unit类型的()。

    var n = 1;val while1 = while(n <= 10){n += 1}println(while1) // ()println(n) // 11var (sum, num) = (0, 100)while (num >= 0) {sum += num;num = num - 1; //scala不能num --   步长}println(sum)

3.3 for表达式

if 循环守卫:引入循环保护式(也称条件判断式,守卫)。保护式为true则进入循环体内部,为false则跳过,类似于continue

  • 单层for循环
    for (i <- 1 to 10){println(i)}for (i <- 1 to 10 if i % 2 == 0){println(i)}var skills = Array("Hadoop", "Spark", "Storm", "Hive", "HBase", "Kafka")for (skill <- skills) {println(skill)}
  • 双重for循环
//两种for循环等价for(i <- 1 to 3 ; j <- 1 to 3 ; if i != j){println((10 * i + j) + " ")}for(i <- 1 to 3){for(j <- 1 to 3){if(i != j){println((10 * i + j) + " ")}}}
  •  使用{} 替代()

注:{}()对于for表达式来说都可以。for 推导式有一个不成文的约定:当for 推导式仅包含单一表达式时使用原括号,当其包含多个表达式时使用大括号。值得注意的是,使用原括号时,早前版本的Scala 要求表达式之间必须使用分号。

这里的写法和前面的等价

   for{i <- 1 to 3 ;j <- 1 to 3 ; if i != j}{println((10 * i + j) + " ")}for{i <- 1 to 3j <- 1 to 3if i != j} {println((10 * i + j) + " ")}

3.4 foreach表达式 

对集合中的元素做遍历

var skills = Array("Hadoop", "Spark", "Storm", "Hive", "HBase", "Kafka")
skills.foreach(x => println(x))

3.5 yeild 关键字

循环返回值:  将遍历过程中处理的结果返回到一个新集合中,使用yield关键字

    val for5 = for(i <- 1 to 10 if i % 2 == 0) yield iprintln(for5) // Vector(2, 4, 6, 8, 10)

4. 函数

4.1 函数的定义和使用

4.2 默认参数

 默认参数:在函数定义时,允许制定参数的默认值

object DefaultParam extends App {def printMessage(name: String = "itcats", age: Int = 18, country: String = "中国"): Unit = {println(s"$name $age $country")}printMessage()printMessage("zp")printMessage(age = 20, country = "美国")
}

4.3 命名参数

传统方式:实参和形参的顺序要一致

命名参数: 定义函数参数的名字,可以不按照顺序进行传参

object Function2 {def main(args: Array[String]): Unit = {//常规调用方式speed(100, 10)//命名参数调用方式1speed(distance = 100, time = 10)//命名参数调用方式2 (调换顺序)speed(time = 10, distance = 100)}//演示命名参数def speed(distance: Int, time: Int): Unit = {println(distance / time)}
}

4.4 可变参数

  • 演示可变参数 在参数类型后加一个通配符* 即可
  • 可变参数要放在参数列表中最后的位置
object Function3 {def main(args: Array[String]): Unit = {println(sum(1, 2, 3, 4))}//演示可变参数 在参数类型后加一个通配符* 即可def sum(nums: Int*): Int = {var res = 0;for (num <- nums) {res += num;}res}//可变参数要放在参数列表中最后的位置def sum1(initValue: Int, nums: Int*): Int = {var res = initValue;for (num <- nums) {res += num;}res}}

5. Scala面向对象

5.1 类的定义和使用

  •  占位符_ 的使用只能用var,不能用val
  • var 修饰的属性会自动生成getter / setter方法
  • val 修饰的属性只会生成gettter 方法
  • private [this] 修饰的属性只能在本类中使用
package com.sanqian.scala.lesson3object Test1 {def main(args: Array[String]): Unit = {//创建Person对象val person = new Person()println(person.name + " " + person.age) //null 18person.name = "小明"//person.age = 19 报错  val age 不可变println(person.name + " " + person.age) //小明 18println(person.eat)  //调用person的eat()方法   小明is eatingperson.watchMovie("泰坦尼克号")  //小明 is watching 泰坦尼克号person.printInfo  //调用person中的printInfo()方法    小明的性别是 male// person.gender 报错  private [this] 所修饰的变量只能在其本类访问,故编译不通过}
}//在scala中定义一个类
class Person{//相当于书写了getter/setter(var)var name : String = _   //占位符_   必须为var,不能为val,否则报错 String占位符默认为null//相当于书写了setter(val)val age : Int = 18   //也可以写成 val age = 18private [this] val gender = "male"def printInfo: Unit ={println(name + "的性别是 "+ gender)  //private [this] 可以在本类Person中使用}//定义方法def eat():String = {name + "is eating"}def watchMovie(movieName : String) :Unit = {println(name + " is watching " + movieName)}}

5.2 主构造器和附属构造器

  • 主构造器:紧跟在类后面的参数列表  val或var不可省略,否则第行student.属性(省略var或val的报错,无法访问)
  • 如果成员属性var修饰相当于对外提供getter/setter方法  val修饰相当于对外提供getter方法
package com.sanqian.scala.lesson3//scala构造器演示
object Constructor {def main(args: Array[String]): Unit = {val student = new Student("小明", 20)println("姓名:" + student.name + " 年龄:" + student.age + " 职业:" + student.occupation) //姓名:小明 年龄:20 职业:学生val student2 = new Student("张三", 21, "男")println("姓名:" + student2.name + " 年龄:" + student2.age + " 职业:" + student2.occupation) //姓名:小明 年龄:20 职业:学生}
}//主构造器:紧跟在类后面的参数列表  val或var不可省略,否则第行student.属性(省略var或val的报错,无法访问)
//如果成员属性var修饰相当于对外提供getter/setter方法  val修饰相当于对外提供getter方法
class Student(val name: String, val age: Int) {println("主构造器执行")val occupation: String = "学生"var gender: String = _//附属构造器def this(name: String, age: Int, gender: String) {this(name, age) //附属构造器第一行代码必须调用主构造器或其他附属构造器this.gender = gender}println("主构造器结束")
}

私有主构造器,设置主构造器的访问权限【注意private是放在主构造器前面】 

class Teacher private(var name: String, age: Int) {}

私有附属构造器

class Teacher(var name: String, age: Int) {var sex: String = _//私有辅助构造器private def this(name: String, age: Int, sex: String) = {//在辅助构造器中必须先调用主构造器this(name, age)this.sex = sex}
}

 类的成员属性访问权限:如果类的主构造器中成员属性是private修饰的,它的getter/setter方法都是私有的

class Teacher(private  var name: String, age: Int) {//...
}

修饰类的访问权限,私有类private [this] class XXX 

//类的前面加上private 标识这个类在当前包下都见,而且当前包下的子包不可见 默认private[this]
private[this] class Teacher(var name: String, val age: Int){}//类的前面加上private[包名] 如private[itcats]表示这个类在itcats包及其子包下都可见
private[itcats] class Teacher(var name: String, val age: Int){}

5.3 继承

  • 在创建子类对象的时候,首先会执行父类的构造方法
  • 从父类继承过来的属性,在子类主构造器中不需要写val/var 
object ExtendApp {def main(args: Array[String]): Unit = {var an = new Bird("鹦鹉",2,"黑色")println(an.name + " "+an.age + " "+ an.color)}
}//父类主构造器
class Animal(val name: String, val age: Int) {println("Animal Constructor in")println("Animal Constructor out")
}//子类主构造
//这里需要注意,从父类继承过来的name,age,在子类主构造器中不需要写var/val , 而color没有继承过来,必须要写var/val
class Bird(name: String, age: Int, val color: String) extends Animal(name, age) {println("Bird Constructor in")println("Bird Constructor out")
}

5.4 重写

  • 对于父类已有的属性和方法,子类重写需要加上override关键字
package com.sanqian.scala.lesson2//重写
object OverwriteApp {def main(args: Array[String]): Unit = {var apple = new Apple("iPhone Xs",4999.9,"黑色")println(apple.toString)}
}//父类主构造器
class Phone(var name: String, val price: Double) {val country = "中国"  //注意: 此处必须为val类型
}//子类主构造
//这里需要注意,从父类继承过来的name,age,在子类主构造器中不需要写var/val , 而color没有继承过来,必须要写var/val
class Apple(name: String, price: Double, val color: String) extends Phone(name, price) {//重写父类的name属性override val country = "美国"   //val country = "美国"报错,必须要加override关键字,并且必须为val 类型  否则将会显示mutable变量不可改变的错误//重写toStirng()方法override def toString() : String = {"name = " + name +" , price = "+ price+" , "+"color = " +color+" , "+"country = " + country}
}

 5.5 抽象类

  1. 抽象类使用abstract关键字修饰,且抽象类中[属性、方法]可以有具体的实现,也可以没有具体的实现
  2. 抽象类没有被实例化不能使用new创建对象
package com.sanqian.scala.lesson4object AbstractApp {def main(args: Array[String]): Unit = {
//    new Person() // 抽样类没有被实例化,不能创建对象val student = new Student3()println(student.name)student.speak}
}/*** 类的一个或多个属性、方法没有完整的实现(只有定义,没有实现)*/
abstract class Person {def speakval name: Stringval age: Int
}class Student3 extends Person{override def speak: Unit = {print("speak...")}override val name: String = "zhangsan"override val age: Int = 22
}

 5.6 伴生类和伴生对象

  1.  如果有一个class,还有一个与class同名的object,那么就称这个object时class的伴生对象,class是object的伴生类
  2. 在 Scala 中,是没有 static 这个东西的,但是它也为我们提供了单例模式的实现方法,那就是使用关键字 object。object中定义的成员变量和方法都是静态的
  3. Scala 中使用单例模式时,除了定义的类之外,还要定义一个同名的 object 对象,它和类的区别是,object对象不能带参数。
  4. 类和它的伴生对象可以互相访问其私有成员方法和属性
  5. 伴生对象可以访问类中的私有方法private,不能访问private[this]修饰的成员变量即方法
package com.sanqian.scala.lesson4object ApplyApp {def main(args: Array[String]): Unit = {
//    for(i <- 1 to 10){
//      ApplyTest.incr
//    }
//    print(ApplyTest.count) // 10, 说明object 本身就是一个单例对象val b = ApplyTest() // ==> Object.applyval c = ApplyTest() // ==》Object.applyc() // Class.apply// 面试重点,结论:// 类名() ==> Object.apply// 对象() ==> Class.apply}
}//伴生类
class ApplyTest{def apply() = {println("class ApplyTest apply...")}
}//伴生对象
object ApplyTest{println("object ApplyTest enter....")var count = 0def incr = {count += 1}// 最佳实践: 在Object的中apply方法中去new Classdef apply(): ApplyTest = {println("Object ApplyTest apply...")new ApplyTest()}println("object ApplyTest leave....")
}

输出:

object ApplyTest enter....
object ApplyTest leave....
Object ApplyTest apply...
Object ApplyTest apply...
class ApplyTest apply...

面试重点,结论:
    // 类名() ==> 调用Object.apply
    // 对象() ==> 调用Class.apply

最佳实践: 在Object的中apply方法中去new Class

 5.7 case class 

  1. 与普通类的区别是不用new,可以直接调用
  2. 通常用在模式匹配
object CaseClassAPP {def main(args: Array[String]): Unit = {println(Dog("wangcai").name)}
}case class Dog(name: String)

5.8 Trait

  1. Scala Trait(特征) 作用相当于 Java 的接口,实际上它比接口还功能强大。与接口不同的是,它还可以定义属性和方法的实现。
  2. 一般情况下Scala的类只能够继承单一父类,但是如果是 Trait(特征) 的话就可以继承多个,从结果来看就是实现了多重继承。
  3. 如果特质中trait某个方法有具体的实现,在子类继承重写的时候必须使用override关键字。如果特质方法没有具体的实现,子类在实现的时候可以不加override关键字也可以加

 一个类可以继承多个特质使用with进行连接

总结:

1、类与对象都可以混入一个或多个特质

2、特质中可以定义有具体实现的方法和没有具体实现的方法

3、如果一个类或者一个对象(继承)混入了某一个特质,这个特质中有一个未被实现的方法A和一个已实现的方法B

这个类或对象必须实现这个没有实现的方法A,且可选择性的重写方法B,必须使用override关键字。

提问:Scala中特质trait与抽象类abstract的区别?

优先使用特质trait。一个类扩展多个特质trait是很方便的,但却只能扩展一个抽象类。
如果你需要构造函数参数,使用抽象类。因为抽象类可以定义带参数的构造函数,而特质不行。例如:
trait t(i: Int) {},参数i是非法的。

 6. Scala集合

1. Scala同时支持可变集合(比如Java中的ArrayList , 长度可以动态改变)和不可变集合(比如Java中的数组,一旦初始化长度不可改变),不可变集合从不可变,可以安全的并发访问。

2. 两个主要的包:

不可变集合:scala.collection.immutable (默认使用)

可变集合:  scala.collection.mutable

3. Scala默认采用不可变集合,对于几乎所有的集合类,Scala都同时提供了可变和不可变的版本。

4. Scala 的集合有三大类:序列 Seq、集 Set、映射 Map,所有的集合都扩展自 Iterable 特质 在 Scala 中集合有可变(mutable)和不可变(immutable)两种类型,immutable 类型的集合 初始化后就不能改变了(注意与 val 修饰的变量进行区别)

  • 5. 不可变集合的继承层次
  •  6. 可变集合的继承层次 : 略

6.1 定长数据Array

  •  使用new 的方式创建数据不够优雅,可以使用下面这种

  • 其他操作: 求和、最大值、最小值、打印

 6.2 可变数组ArrayBuffer 

  • 可变数组:长度可变、内容可变

  • 可变数组与不可变数组的转换
arr1.toBuffer
arr2.toArray

  • 遍历数组 

两种方式

  • 反转打印数组

 6.3 定长List

  1. Nil就是一个空的list
  2. l.head : 获取第一个元素
  3. l.tail : 获取除第一个元素之外其他元素
  4. 使用:: 合并List()数组

 6.3 可变List

  • 增加元素

  • 减少元素 

 

  •  可变List转定长List

 

  • 实现一个求和( :_* 可把Seq转换成可变参数)

 

 6.4 Set

  1. set 是一个无序的不重复的集合
  2. 可变Set   collection.mutable.HashSet
scala> val hset = collection.mutable.HashSet(1,3,4)
hset: scala.collection.mutable.HashSet[Int] = Set(1, 3, 4)scala> val set = Set(1,2,3,3)
set: scala.collection.immutable.Set[Int] = Set(1, 2, 3)scala> hset.add(5)
res26: Boolean = truescala> hset
res27: scala.collection.mutable.HashSet[Int] = Set(1, 5, 3, 4)scala> hset.add(1)
res28: Boolean = falsescala> hset.remove(1)
res29: Boolean = truescala> hset.remove(999)
res30: Boolean = falsescala> hset.-=(3)
res31: hset.type = Set(5, 4)scala> hset ++ Set(0,9)  //++ 原集合数值无变化
res33: scala.collection.mutable.HashSet[Int] = Set(0, 9, 5, 4)scala> hset ++= Set(0,9)  //++=原集合数据发生变化
res34: hset.type = Set(0, 9, 5, 4)

7. 模式匹配

7.1 最基础的模式匹配

object BaseMatch {val a: Array[String] = Array("a,", "b", "c", "d")val name: String = a(Random.nextInt(a.length))name match {case "a" => println("This is a")case "b" => println("This is b")case "c" => println("This is c")case "d" => println("This is d")case _   => println("Can not find it")}def matchMethod(num : Int) :String = num match {case 1 => "This is a"case 2 => "This is b"case 3 => "This is c"case 4 => "This is d"case 4 => "This is e"case _ => "Can not fiSnd it"}def main(str: Array[String]): Unit = {//一旦匹配上就直接退出模式匹配matchMethod(4)  //返回是"This is d"}
}

7.2 加条件进行匹配

object BaseMatch extends App {print(matchMethod("haha",4))   //This is ddef matchMethod(keyword: String, num: Int): String = num match {case 1 => "This is a"case 2 => "This is b"case 3 => "This is c"case 4 if (keyword == "haha") => "This is d" // 双重过滤case _ => "Can not fiSnd it"}
}

7.3 Array模式匹配
 

def who(arr : Array[String]): Unit = arr match {//只匹配数组中含有一个"zhangsan"的casecase Array("zhangsan") => println("This is zhangsan")case Array("zhangsan","lisi") => println("This is zhangsan and lisi")//匹配数组中只含三个元素的case(对元素没有要求)case Array(x,y,z) => println("This is x,y,z")//匹配第一个为wangwu,后可有可无任意多个元素的casecase Array("wangwu",_*) => println("This is wangwu and others")case _ => println("who is it?")}

7.4 List模式匹配

与Array的模式匹配十分相似

def whoList(list : List[String]): Unit = list match {//只匹配数组中含有一个"zhangsan"的casecase "zhangsan"::Nil => println("This is zhangsan")case "zhangsan"::"lisi"::Nil => println("This is zhangsan and lisi")//匹配数组中只含三个元素的case(对元素没有要求)case x::y::z::Nil => println("This is x,y,z")//匹配第一个为wangwu,后可有可无任意多个元素的casecase "wangwu"::tail => println("This is wangwu and others")case m :: n => println("匹配拥有head,tail的List集合")case _ => println("who is it?")}

7.5 类型匹配

 //类型模式匹配matchType(Map("haha" -> "hehe"))def matchType(obj : Any): Unit = {obj match{case x:Int => println("Int")case y:String => println("String")case z:Map[_,_] => z.foreach(println)case _ => println("unkown")}}

7.6 Scala异常处理

//Scala中的异常处理
object MyException extends App {try{val i = 1 / 0; //制造异常}catch {case e:ArithmeticException => println("除数不能为0")case e:Exception => println("出现了未知异常")}finally {println("关闭资源处理")}
}

7.7 case class 模式匹配

object CaseClassMatch extends App {def caseMatch(plane : Plane): Unit = plane match {case Boeing(name: String, age: Int) => println("This is boeing 787 , age is 2")case Airbus(name: String, age: Double) => println("This is airbus 330 , age is 0.8")case Other(name: String, age: Int) => println("This is 战斗机 , age is 7")}caseMatch(Boeing("播音787",2))caseMatch(Airbus("空客330",0.8))caseMatch(Other("战斗机",7))
}class Planecase class Boeing(name: String, age: Int) extends Plane {}case class Airbus(name: String, age: Double) extends Plane {}case class Other(name: String, age: Int) extends Plane {}

8. Scala高级函数
 

8.1 字符串高级操作

  1. 字符串的插值:'s'允许在处理字符串时直接使用变量,可以加{} 也可以不加{}
  2. 多行字符串的表示: 使用三引号""" """ (与python用法相同)
object StringApi extends App {val name = "itcats_cn"val job = "student"val age = 999.999d//普通输出 加了, 会自动产生一个()println("name=" + name, "job=" + job)  //输出结果 (name=itcats_cn,job=student)// 文字'f'插值器允许创建一个格式化的字符串,类似于 C 语言中的 printf。// 在使用'f'插值器时,所有变量引用都应该是 printf 样式格式说明符,如%d,%i,%f 等。println(f"姓名: $name%s 年龄: $age%1.2f 职业: $job") // 该行输出有换行printf("姓名: %s 年龄: %1.2f 职业: %s", name, age, job) // 该行输出没有换行// 's'允许在处理字符串时直接使用变量。// 在println语句中将String变量($name)附加到普通字符串中。println()println(s"姓名: ${name} 年龄: $age 职业: $job")   //可以{}也可以不{}// 字符串插入器还可以处理任意表达式。// 使用's'字符串插入器处理具有任意表达式(${1 + 1})的字符串(1 + 1)的以下代码片段。 任何表达式都可以嵌入到${}中。println(s"1 + 1 = ${1 + 1}")  // 1 + 1 = 2//多行字符串演示(连续输入三个"后按回车)val c ="""|Hello|World""".stripMarginprintln(c)
}

8.2 匿名函数

匿名函数: 函数是可以命名的,也可以不命名
语法: (参数名: 参数类型...) => 函数体

//匿名函数:函数是可以命名也可以匿名的
object AnonymityApp extends App {//命名函数定义def hello(name: String): Unit = {println(s"Hello : $name")}//匿名函数可以传递给变量val f = (name:String) => println(s"Hello : $name")//也可以传递给函数def an = (name:String) => println(s"Hello : $name")//调用hello("a")f("b")an("c")
}

8.3 currying函数(柯里化函数)

 柯里化: 将接收一个参数的函数,转换成2个

object CurryApp extends App {//curry函数:将原来接收两个参数的一个函数,转换成2个//原函数写法def sum(a: Double, b: Double): Double = {a + b}//curry函数def currySum(a: Double)(b: Double): Double = {a + b}//柯里化的演变过程def add(x: Int) = (y: Int) => x + y //(y: Int) => x + y 为一个匿名函数, //也就意味着 add 方法的返回值为一个匿名函数//高阶函数,方法的参数是函数或方法的返回值是函数的函数//调用println(   sum(1,1)         )println(   currySum(1)(1)   )
}

8.4 高阶函数

map :逐个去操作集合中的每个元素

object HighLevelFunction extends App {val l = List(1, 2, 3, 4, 5)//1.map 逐个操作集合里面的每个元素 实际上是建立一种映射关系,返回的是一个新的数组l.map((x: Int) => x + 1) //将List内的每个元素(x:Int) + 1l.map(x => x + 1)        //scala能帮我们推断出List内每个元素是Int,且只有一个元素时候,括号可以省略l.map(_ + 1)             //对List中的任意元素都 + 1//遍历l.map(_ + 1).foreach(print)    //23456 List[Int]println()println("-------------")//2.在map取出每个元素 + 1的基础上,使用filter过滤出 < 4的数字l.map(_ + 1).filter(_ < 4).foreach(print)   //23  List[Int]println()println("-------------")//3.使用take取集合中的前3个元素l.take(3).foreach(print)      //123    List[Int]println()println("-------------")//4.reduceprint(  l.reduce(_ + _)  )  //15     Int  将l集合中的前后元素两两相加 1+2 3+3 6+4 10+5println()println("-------------")//5.reduceLeft = reduceprint(  l.reduceLeft(_ - _)  )   //-13  1 - 2 - 3 - 4 - 5 = -13println()println("-------------")//6.reduceRightprint(  l.reduceRight(_ - _)  )  //3   ( 1 - ( 2 - ( 3 - ( 4 - 5 ))))println()println("-------------")//7.fold(第一个括号代表初始值)print(  l.fold(0)(_ - _)  )    //-15  0-1-2-3-4-5 = -15println()println("-------------")//8.foldLeft = fold  (0在最左边)print(  l.foldLeft(0)(_ - _))  //-15  0-1-2-3-4-5 = -15println()println("-------------")//9.foldRight        (0在最右边)print(  l.foldRight(0)(_ - _) ) //3    ( 1 - ( 2 - ( 3 - ( 4 - (5 - 0) ) ) ) )println()println("-------------")//10.flattenval f = List(List(1,2),List(3,4),List(5,6)) //List内部是一个List类型的元祖print(f.flatten)   //flatten可以理解为压扁  List(1, 2, 3, 4, 5, 6)//11.flatMap(可以理解为map + flatten)println()println("-------------")//先来看一个例子,将f中List元祖都扩大两倍(使用map) 第一次使用map取出来的是List(x,y) 第二次用map取出来的是(x,y)print(f.map(_.map(_ * 2)))   //List(List(2, 4), List(6, 8), List(10, 12))println()println("-------------")//flatMap所实现的效果是  List(2, 4, 6, 8, 10, 12)print(f.flatMap(_.map(_ * 2)))println()println("-------------")//12.flatMap的一些应用val t = List("hello,hello,world,hello")// t.flatMap(_.split(","))   List(hello, hello, world, hello)t.flatMap(_.split(",")).map(x => (x,1)).foreach(println)/*** 输出:*   (hello,1)(hello,1)(world,1)(hello,1)*/
}

并行聚合 

scala> list.aggregatedef aggregate[B](z: => B)(seqop: (B, Int) => B,combop: (B, B) => B): Bscala> list.aggregate(0)(_ + _ , _ + _)
res6: Int = 10

并集union 

scala> list
res7: List[Int] = List(1, 2, 3, 4)scala> val list1 = List(1,6)
list1: List[Int] = List(1, 6)scala> list.union(list1)
res20: List[Int] = List(1, 2, 3, 4, 1, 6)

交集intersect

scala> list.intersect(list1)
res21: List[Int] = List(1)

差集diff

scala> list.diff(list1)
res22: List[Int] = List(2, 3, 4)

角标元素合并组合成元组zip

scala> list
res23: List[Int] = List(1, 2, 3, 4)scala> list1
res24: List[Int] = List(1, 6)scala> list.zip(list1)
res25: List[(Int, Int)] = List((1,1), (2,6))

9. Scala隐式转换

10. Scala操作外部数据

包括文件、网络数据、MySQL、XML等外部数据

10.1 操作文件/网络资源

//使用scala操作File文件
object FileTest {def main(args: Array[String]): Unit = {//读取文件var file = scala.io.Source.fromFile("/Users/fatah/Desktop/1.txt")(scala.io.Codec.UTF8);//var file = scala.io.Source.fromFile("/Users/fatah/Desktop/1.txt");def readLine(): Unit = {for (line <- file.getLines()) {println(line)}}//调用读取文件资源//readLine//调用读取网络资源readNet//读取网络数据def readNet(): Unit ={var file = scala.io.Source.fromURL("https://www.baidu.com");for(line <- file.getLines()){println(line)}}}
}

10.2 操作XML

10.3 操作MySQL

//使用scala连接数据库,操作MySQL
object MySQLTest {def main(args: Array[String]): Unit = {//书写连接数据库相关信息val url = "jdbc:mysql://localhost:3306/crash_course"val username = "root"val password = "root"//在scala中这一步与Java的class.forName写法有所不同try {classOf[com.mysql.jdbc.Driver]val conn = DriverManager.getConnection(url,username,password)val sql = "select * from orders"val stmt = conn.prepareStatement(sql)val rs = stmt.executeQuery();while(rs.next()){val order_num = rs.getString("order_num")val order_date = rs.getString("order_date")val cust_id = rs.getString("cust_id")println(s"$order_num , $order_date , $cust_id")}}catch {case e : Exception => e.printStackTrace()}finally {//关闭资源,懒得关了,懂就行}}
}


http://chatgpt.dhexx.cn/article/qQ5jj1op.shtml

相关文章

Scala教程-详细全部

版权声明&#xff1a;本文为博主原创文章&#xff0c;遵循 CC 4.0 BY-SA 版权协议&#xff0c;转载请附上原文出处链接和本声明。 本文链接&#xff1a;https://blog.csdn.net/qq_39346903/article/details/113562823 文章目录 第1章 Scala入门1.1 概述1.1.1 为什么学习Scala1.…

单工,半双工和全双工有何区别和联系?

单工、半双工和全双工是电信计算机网络中的三种通信信道。这些通信信道可以提供信息传达的途径。通信信道可以是物理传输介质或通过多路复用介质的逻辑连接。物理传输介质是指能够传播能量波的材料物质&#xff0c;例如数据通信中的导线。并且逻辑连接通常指电路交换连接或分组…

单工、半双工及全双工之间的区别

1、单工数据传输只支持数据在一个方向上传输&#xff1b;在同一时间只有一方能接受或发送信息&#xff0c;不能实现双向通信&#xff0c;举例&#xff1a;电视&#xff0c;广播。 2、半双工数据传输允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输,它实…

全双工、半双工、单工有什么区别!

什么是全双工&#xff1f; 全双工&#xff1a;&#xff08;Full Duplex&#xff09;是通讯传输的一个术语。通信允许数据在两个方向上同时传输&#xff0c;它在能力上相当于两个单工通信方式的结合。全双工指可以同时&#xff08;瞬时&#xff09;进行信号的双向传输&#xff0…

三种通信方式——单工、半双工和双工通信

数据通常是在两个站&#xff08;点对点&#xff09;之间进行传输&#xff0c;按照数据流的方向可分为三种传输模式&#xff1a;单 工、半双工、全双工。 一、单工通信&#xff08;simplex&#xff09; 单工通信只支持信号在一个方向上传输&#xff08;正向或反向&#xff09…

图文并茂~ 详解交换机中的半双工与全双工网络知识

很多学习网络知识的朋友在配置交换机时&#xff0c;时常会看到半双工与全双工的功能&#xff0c;今天带大家一起来了解下什么是半双工与全双工。 早期的网络设备HUB&#xff08;集线器&#xff09;就是半双工&#xff0c;目前基本没有人用了&#xff0c;而现在用的SWITCH&…

[网络管理]全双工与半双工的区别

同事说新办公室的网络一直不稳定&#xff0c;经常掉线延迟。检查进口线路和更换转接网线。都无法解决问题。 估计是不是进口网线中一根或者2根短路&#xff0c;那就修改下网卡属性吧。把自适应改成全双工10M模式&#xff0c;测试OK。 全双工传输 英文写法是:Full&#xff0d;Du…

单工通信、半双工通信和全双工通信

数据通信中&#xff0c;数据在线路上的传送方式可以分为 单工通信、 半双工通信和 全双工通信三种。 ewlw半双工通信&#xff1a;半双工通信是指数据可以沿两个方向传送&#xff0c;但同一时刻一个 半双工总线结构 信道只允许单方向传送&#xff0c;因此又被称为双向交替通信。…

比较全面的HTTP和TCP网络传输的单工、全双工和半双工

文章目录 单工、全双工、半双工1. 单工2. 半双工3. 全双工 HTTP协议的工作模式TCP协议的工作模式 本文参考&#xff1a; 图解网络传输单工、半双工、全双工 - 知乎 (zhihu.com) 问&#xff1a;HTTP是单工的还是双工的还是半双工的 - 简书 (jianshu.com) 关于TCP全双工模式的解释…

简析全双工与半双工的区别

全双工传输英文写法是:Full&#xff0d;Duplex Transmissions 是指交换机在发送数据的同时也能够接收数据&#xff0c;两者同步进行&#xff0c;这好像我们平时打电话一样&#xff0c;说话的同时也能够听到对方的声音。目前的交换机都支持全双工。 全双工的好处在于迟延小&…

全双工与半双工的区别

全双工传输英文写法是:Full&#xff0d;Duplex Transmissions 是指交换机在发送数据的同时也能够接收数据&#xff0c;两者同步进行&#xff0c;这好像我们平时打电话一样&#xff0c;说话的同时也能够听到对方的声音。目前的交换机都支持全双工。 全双工的好处在于迟延小&…

全双工、半双工和单工

一&#xff0c;单工、半双工和全双工的区别&#xff1a; 在串行通信中&#xff0c;数据通常是在两个终端&#xff08;如电脑和外设&#xff09;之间进行传送&#xff0c;根据数据流的传输方向可分为3种基本传送方式&#xff1a;单工、半双工和全双工。这3种传输方式的示意图和区…

单工,半双工和和全双工通讯的概念

单工&#xff1a;数据传输只支持数据在一个方向上传输&#xff1b; 半双工&#xff1a;允许数据在两个方向上传输&#xff0c;但某一时刻只允许数据在一个方向上传输&#xff0c;实际上是一种切换方向的单工通信&#xff0c;不需要独立的接收端和发送端&#xff0c;两者可合并…

单工、半双工和全双工的区别

--------------------------------------------- -- 时间&#xff1a;2018-11-06 -- 创建人&#xff1a;Ruo_Xiao -- 邮箱&#xff1a;xclsoftware163.com --------------------------------------------- 一、单工 1、数据只在一个方向上传输&#xff0c;不能实现双方通信。…

单工、双工、半双工、全双工通信常识

根据通信双方的分工和信号传输方向可将通信分为三种方式&#xff1a;单工、半双工与全双工。 单工通信&#xff0c;指通信双方设备中发送器与接收器分工明确&#xff0c;只能在由发送器向接收器的单一固定方向上传送数据&#xff0c;并且不能实现双向通信&#xff0c;例如&…

网络传输单工、半双工、全双工的解读

来源 在网络传输中&#xff0c;数据在线路上的传送方式可以分为单工通信、半双工通信和全双工通信三种。以下我们将通过简单的叙述方式&#xff0c;配图了解这三种方式的定义和区别。 一、单工 定义&#xff1a;单工数据传输只支持数据在一个方向上传输。 举例&#xff1a;意思…

单工通信、半双工通信和全双工通信的区别

对于点对点之间的通信&#xff0c;按照消息传送的方向与时间关系&#xff0c;通信方式可分为单工通信、半双工通信及全双工通信三种。 一、单工通信 单工通信&#xff08;Simplex Communication&#xff09;是指消息只能单方向传输的工作方式。 在单工通信中&#xff0c;通信…

【网络基础】半双工和全双工

讨论在网络中使用的两种不同的传输类型。 半双工&#xff08;half duplex&#xff09;和全双工&#xff08;full duplex&#xff09;。 引入基带传输、宽带传输两种传输频带&#xff0c;并讨论全双工的实现。 半双工 在半双工的网络中&#xff0c;两个设备使用网络电缆互连成一…

【数据存储】分布式文件系统SeaweedFS

2021.05.25 初始seaweedFS 安装 1、先去GitHub下载所需版本 linux_amd64.tar.gz2、然后放到服务器的文档中 /opt/software3、解压安装 tar -zxvf ./linux_amd64.tar.gz -C /opt/install/seaweed4、在seaweed安装包下安装seaweedfs文件夹及其下属两个文件夹 mkdir -p ./se…

seata

Seata 1 seata概述 1.1 Seata简介 Seata 是一款开源的分布式事务解决方案&#xff0c;致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式&#xff0c;为用户打造一站式的分布式解决方案。 1.1.1 AT 模式 基于支持本地 ACID…