1 初识 Scala
1.1 Scala 概述
Scala 是一门多范式的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性。
Scala 是运行于 Java 平台(Java 虚拟机)上,并兼容现有的 Java 程序。
Scala 的编译模型(独立编译,动态类加载)与 Java 和 C# 一样,所有 Scala 代码可以调用 Java 类库(对于 .NET 实现则可调用 ,NET 类库)。
2 Scala 入门
2.1 var 和 val 的区别
var:变量,可以修改值
val:值,不能修改值
2.2 lazy 在 Scala 中的应用
scala> lazy val age = 10
age: Int = <lazy>
scala> age
res0: Int = 10
//返回一个lazy,只有真正执行时才会赋值
scala> val age = 10
age: Int = 10
2.3 基本数据类型
Byte/Char
Short/Int/Long/Float/Double
Boolean
3 Scala 函数
3.1函数的定义和使用
def 方法名(参数名:参数类型) : 返回值类型 = {
// 括号内的叫做方法体
// 方法体内的最后一行为返回值,不需要使用 return
}
方法中只有一行代码,可以省略 {}
方法中没有参数,调用时可以省略 ()
3.2 默认参数
def 方法名(参数名:参数类型 = 值) : 返回值类型 = {
}
在函数定义时,允许指定参数的默认值
3.3 命名参数
def 方法名(参数名:参数类型) : 返回值类型 = {
}
在函数调用时,允许指定参数的属性名进行传值
3.4 可变参数
def 方法名(参数名:参数类型 *) : 返回值类型 = {
}
在函数调用时,允许传递多个属性值
3.5 条件表达式
if (command) true else false
3.6 循环表达式
to 左闭右闭
scala> for (i <- 1 to 10) {}
Range 左闭右开
scala> for (i <- Range(1, 10)) {}
until 左闭右开
scala> for (i <- 1.until(10)) {}
循环守卫
scala> for (i <- 1 to 10 if i % 2 == 0) {}
循环遍历
scala> val courses = Array("Hadoop", "Spark SQL", "Spark Streaming", "Strom", "Scala")
courses: Array[String] = Array(Hadoop, Spark SQL, Spark Streaming, Strom, Scala)
scala> courses.foreach(course => println(course))
Hadoop
Spark SQL
Spark Streaming
Strom
Scala
4 Scala 对象
4.1 面向对象概述
封装:属性、方法封装到类中
继承:父类和子类之间的关系,子类继承父类的属性和方法
多态:父类引用指向子类对象
4.2 类的定义和使用
class People {
// 定义属性
var name : String = _
val age: Int = 10
// 只能在class中使用
private [this] val gender = "male"
def printInfo(): Unit = {
println("gender: " + gender)
}
def eat(): String = {
name + "eat..."
}
def watchFootball(teamName : String): Unit = {
println(name + "is watching match of " + teamName)
}
}
4.3 主构造器和辅助构造器
// 主构造器
class Person(val name:String, val age:Int) {
println("Person Constructor enter...")
var school = "ustc"
var gender:String = _
// 辅助构造器
def this(name:String,age: Int, gender:String) {
// 辅助构造器的第一行代码必须调用主构造器或辅助构造器
this(name,age)
this.gender = gender
}
println("Person Constructor leave...")
}
4.4 继承
// 子类继承父类时父类已有的属性直接继承,没有的属性必须加var或val
class Student(name: String, age: Int, var major: String) extends Person(name, age) {
println("Student Constructor enter...")
println("Student Constructor leave...")
}
4.5 重写
// 子类继承父类时父类已有的属性直接继承,没有的属性必须加var或val
class Student(name: String, age: Int, var major: String) extends Person(name, age) {
println("Student Constructor enter...")
// 重写父类继承的属性或方法时,必须加override关键字
override var school = "peking"
override def toString = "Student: override def toString"
println("Student Constructor leave...")
}
4.6 抽象类
/**
* 类的一个或者多个方法没有完整的实现,只有定义
*/
abstract class Person2 {
def speak
var name: String
val age: Int
}
class Student2 extends Person2 {
override def speak: Unit = {
println("speak")
}
override var name: String = _
override val age: Int = 10
}
4.7 伴生类和伴生对象
如果有一个 class,还有一个同名的 object,那么就称 object 是 class 的伴生对象 ,class 是 object 的伴生类
4.8 apply 方法
object ApplyApp {
def main(args: Array[String]): Unit = {
for (i <- 1 to 10) {
ApplyTest.incr
}
// object是一个单例对象
println(ApplyTest.count)
// 类名() => Object.apply
// 对象() => Class.apply
val apply1 = ApplyTest()
val apply2 = new ApplyTest()
apply2()
}
}
class ApplyTest {
def apply() = {
println("Class ApplyTest apply...")
}
}
object ApplyTest {
var count = 0
def incr = {
count = count + 1
}
// 最佳实践:在Object的apply方法中new Class
def apply() = {
println("Object ApplyTest apply...")
}
}
4.9 case class
object CaseClassApp {
def main(args: Array[String]): Unit = {
println(Dog("大黄").name)
}
}
//case class不用new,通常用于模式匹配
case class Dog(name: String) {
}
4.10 trait
在 trait 中方法是抽象方法,不给出具体的方法体
在 Scala 中无论是继承还是实现都使用 extends,必须实现其中的抽象方法,实现时不需要使用 override 关键字,同时 Scala 同 Java 一样,不支持多继承类,但是支持多继承接口,使用 with 关键字
class xxx extends xxxclass {}
class xxx extends xxxtarit {}
class xxx extends xxxclass with xxxtrait {}
class xxx extends xxxtrait with xxxtarit1 ... {}
5 Scala 集合
5.1 定长数组
scala> val a = new Array[String](5)
a: Array[String] = Array(null, null, null, null, null)
scala> println(a.mkString(","))
null,null,null,null,null
scala> val b = Array("Hadoop", "Spark", "Storm")
b: Array[String] = Array(Hadoop, Spark, Storm)
scala> println(b.mkString(","))
Hadoop,Spark,Storm
scala> val c = Array(2, 3, 4, 5, 6, 7, 8, 9)
c: Array[Int] = Array(2, 3, 4, 5, 6, 7, 8, 9)
scala> println(c.mkString(","))
2,3,4,5,6,7,8,9
5.2 变长数组
var d = scala.collection.mutable.ArrayBuffer[Int]()
// 添加元素
d += 1
d += (2, 3, 4, 5)
// 添加数组
d ++= c
// 在指定位置添加元素
d.insert(0, 0)
// 删除指定位置的元素
d.remove(1)
// 从指定位置开始删除多少个元素
d.remove(0, 3)
// 从末尾删除多少个元素
d.trimEnd(2)
// 转换成不可变数组
d.toArray
5.3 List
// 不可变列表
val l = List(1, 2, 3, 4, 5)
// Nil表示一个空的集合
val l2 = 1 :: Nil
// 将1作为head,将后面的作为tail
val l3 = 1 :: 2 :: l :: Nil
val l4 = 1 :: 2 :: l :: 4 :: Nil
// 可变列表
val l5 = scala.collection.mutable.ListBuffer[Int]()
l5 += 1
l5 += (2, 3, 4, 5)
l5 ++= List(6, 7, 8, 9)
l5 -= 1
l5 -= (1,2,3)
l5 --= List(2, 3, 4, 5)
l5.toList
5.4 Set
和 List 类似,区别是 Set 无序且不重复
5.5 Map
// 不可变Map
val a = Map("PK" -> 18, "zhangsan" -> 30)
// 可变Map
var b = scala.collection.mutable.Map("PK" -> 18, "zhangsan" -> 30)
// 空Map
var c = scala.collection.mutable.HashMap[String, Int]()
println(b.get("lisi"))
println(b.get("lisi").get)
println(b.getOrElse("lisi", "default"))
5.7 Option&Some&None
Option[T] 是一个类型为 T 的可选值的容器:
如果值存在, Option[T] 就是一个 Some[T] ;
如果不存在, Option[T] 就是对象 None 。
5.8 Tuple
var a = (1,2,3,4,5)
for (i <- 0 until (a.productArity)) {
println(a.productElement(i))
}
// 通过元祖._索引取值,索引从1开始
println(a._1)
6 Scala 模式匹配
6.1 最基础的模式匹配
val names = Array("Dennis Ritchie", "James Gosling", "Brendan Eich", "John McCarthy")
val name = names(Random.nextInt(names.length))
name match {
case "Dennis Ritchie" => println("names[0]")
case "James Gosling" => println("names[1]")
case "Brendan Eich" => println("names[2]")
case _ => println("names[3]")
}
6.2 加条件进行匹配
def judgeGrade(name: String, grade: String): Unit = {
grade match {
case "A" => println("Excellent...")
case "B" => println("Good...")
case "C" => println("Just so so...")
case _ if (name == "PK") => println(name + ", you need work hard...")
case _ => println("You need work hard...")
}
}
6.3 Array 模式匹配
def greeting(array: Array[String]): Unit = {
array match {
case Array("zhangsan") => println("Hi:zhangsan")
case Array(x,y) => println("Hi:" + x + "," + y)
case Array("zhangsan", _*) => println("Hi:zhangsan and other")
case _ => println("Hi:...")
}
}
6.4 List 模式匹配
def greeting(list: List[String]): Unit = {
list match {
case "zhangsan" :: Nil => println("Hi:zhangsan")
case x :: y :: Nil => println("Hi:" + x + "," + y)
case "zhangsan" :: tail => println("Hi:zhangsan and other")
case _ => println("Hi:...")
}
}
6.5 类型匹配
def matchType(obj: Any): Unit = {
obj match {
case x: Int => println("Int")
case s: String => println("String")
case m: Map[_, _] => println("Map")
case _ => println("other")
}
}
6.6 Scala 异常处理
try {
var i = 10 / 0
println(i)
} catch {
case e: ArithmeticException => println("除数不能为0")
case e: Exception => println(e.getMessage)
} finally {
// 释放资源
}
6.7 case class 模式匹配
class Person
case class CTO(name:String, floor:String) extends Person
case class Employee(name:String, floor:String) extends Person
case class Other(name:String, floor:String) extends Person
def caseclassMatch(person: Person): Unit = {
person match {
case CTO(name,floor) => println("CTO name is: " + name + ", floor is: " + floor)
case Employee(name,floor) => println("Employee name is: " + name + ", floor is: " + floor)
case _ => println("Other")
}
}
6.8 Some None 模式匹配
def getGrade(name:String): Unit = {
val grade = map.get("name")
grade match {
case Some(grade) => println("you grade is: " + grade)
case None => println("None")
}
}
7 Scala 函数高级操作
7.1 字符串高级操作
插值表达式
scala> println(s"Hello $name")
Hello PK
多行字符串
"""
|xxx
|xxx
|xxx
|""".stripMargin
7.2 匿名函数
(参数名 : 参数类型) => {
// 方法体
}
7.3 currying 函数
将原来接收两个参数的一个函数,转换成 2 个
def (参数名 : 参数类型) (参数名 : 参数类型) : 返回值类型 = {
// 方法体
}
方法名(值)(值)
7.4 高阶函数
Map
map 操作是针对集合的典型变换操作,它将某个函数应用到集合中的每个元素,并产生一个结果集合
scala> val books = List("Hadoop", "Hive", "HDFS")
books: List[String] = List(Hadoop, Hive, HDFS)
scala> books.map(s => s.toUpperCase)
res0: List[String] = List(HADOOP, HIVE, HDFS)
Filter
filter 操作是遍历一个集合并从中获取满足指定条件的元素组成一个新的集合
val university = Map("XMU" -> "Xiamen University", "THU" -> "Tsinghua University","PKU"->"Peking University","XMUT"->"Xiamen University of Technology")
然后我们采用 filter 操作过滤得到那些学校名称中包含 Xiamen 的元素:
val universityOfXiamen = university filter {kv => kv._2 contains "Xiamen"}
FlatMap
flatMap 是 map 的一种扩展,在 flatMap 中,我们会传入一个函数,该函数对每个输入都会返回一个集合(而不是一个元素),然后,flatMap 把生成的多个集合拍扁成为一个集合
scala> val books = List("Hadoop","Hive","HDFS")
books: List[String] = List(Hadoop, Hive, HDFS)
scala> books flatMap (s => s.toList)
res0: List[Char] = List(H, a, o, o, p, H, i, v, e, H, D, F, S)
Reduce
reduce 归纳、简化的意思,把容器中的元素作参数传给里面的二元匿名函数
reduce 包含 reduceLeft 和 reduceRight 两种操作,前者从集合的头部开始操作,后者从集合的尾部开始操作
scala> val list = List(1,2,3,4,5)
list: List[Int] = List(1, 2, 3, 4, 5)
scala> list.reduceLeft(_ + _)
res21: Int = 15
scala> list.reduceRight(_ + _)
res22: Int = 15
Fold
折叠操作和归约操作比较类似,fold 操作需要从一个初始的种子值开始,并以该值作为上下文,处理集合中的每个元素
scala> val list = List(1,2,3,4,5)
list: List[Int] = List(1, 2, 3, 4, 5)
scala> list.fold(10)(_*_)
res0: Int = 1200
可以看出,fold 函数实现了对 list 中所有元素的累乘操作,fold 函数需要两个参数,一个参数是初始种子值,这里是 10,另一个参数是用于计算结果的累计函数,这里是累乘。
执行 list.fold(10)(_*_) 时,首先把初始值拿去和 list 中的第一个值 1 做乘法操作,得到累乘值 10,然后再拿这个累乘值 10 去和 list 中的第 2 个值 2 做乘法操作,得到累乘值 20,依此类推,一直得到最终的累乘结果 1200
fold 有两个变体:
- foldLeft(),第一个参数为累计值,集合遍历的方向是从左到右
- foldRight(),第二个参数为累计值,集合遍历的方向是从右到左,对于fold()自身而言,遍历的顺序是未定义的,不过,一般都是从左到右遍历
7.5 偏函数
8 Scala 隐式转换
8.1 隐式转换概述
为一个已存在的类添加一个新的方法的过程
8.2 隐式转换实战
object ImplicitApp {
def main(args: Array[String]): Unit = {
// 定义格式转换函数
implicit def man2superMan(man:Man) = new SuperMan(man.name)
val man = new Man("PK")
man.fly()
implicit def file2RichFile(file: File) = new RichFile(file)
val file = new File("")
file.read()
}
}
class Man(val name:String) {
def eat(): Unit = {
println(s"name [ $name ] eat ....")
}
}
class SuperMan(val name:String) {
def fly(): Unit = {
println(s"name [ $name ] fly ....")
}
}
class RichFile(val file:File) {
def read() = {
scala.io.Source.fromFile(file.getPath).mkString
}
}
8.3 隐式转换切面封装
object ImplicitAspect {
implicit def man2superMan(man: Man) = new SuperMan(man.name)
implicit def file2RichFile(file: File) = new RichFile(file)
}
然后在其他需要隐式转换的类中导入
8.4 隐式类
object ImplicitClassApp {
def main(args: Array[String]): Unit = {
println(1.add(3))
}
// 表示将所有的int类型增加了add方法
implicit class Cal(x: Int) {
def add(a: Int) = a + x
}
}
9 Scala 操作外部数据
9.1 Scala 读取文件及网络数据
object FileApp {
def main(args: Array[String]): Unit = {
val file = Source.fromFile("C:\\Users\\Administrator\\Desktop\\test.txt")(scala.io.Codec.UTF8)
readLine()
readNet()
def readLine( ): Unit = {
for (line <- file.getLines()) {
println(line)
}
}
def readChar(): Unit = {
for (elem <- file) {
println(elem)
}
}
def readNet(): Unit = {
val file = Source.fromURL("http://www.baidu.com")
for (elem <- file.getLines()) {
print(elem)
}
}
}
}
9.2 Scala 读取 MySQL 数据
object MySQLApp {
def main(args: Array[String]): Unit = {
val url = "jdbc:mysql://localhost:3306/mysql"
val username = "root"
val password = "123456"
var connection: Connection = null
try{
classOf[com.mysql.jdbc.Driver]
connection = DriverManager.getConnection(url, username, password)
val statement = connection.createStatement()
val resultSet = statement.executeQuery("select User,Host from user")
while (resultSet.next()) {
val host = resultSet.getString("host")
val user = resultSet.getString("user")
println(s"$user -> $host")
}
}catch {
case e:Exception => println(e.getMessage)
} finally {
if (connection != null)
connection.close()
}
}
}
9.3 Scala 读取 XML 文件
def readValue(): Unit = {
val xml = XML.load(this.getClass.getClassLoader.getResource("book.xml"))
// headerField
val headerField = xml \ "book" \ "field"
// all fields
val fields = xml \\ "field"
// header/field/name
val fieldAttributes = (xml \ "book" \ "field").map(_ \ "@name")
// all message == Logon
val filters = (xml \\ "message").filter(_.attribute("name").exists(_.text.equals("Logon")))
// header/field content
val seq = (xml \ "header" \ "field").map(x => (x \ "@name", x.text, x \ "@required"))
}
网友评论