虽然scala包含了面向对象编程和函数式编程的能力,但是他更侧重函数式编程。
写spark程序,只会用到一点点scala的基本功能,所以只需要学一点点scala就可以了。
自带的类型:这些都是类,scala没有类似int、long这样的基本数据类型
Byte、Short、Int、Long、Float、Double、Char、String、Boolean、
变量:不可变变量(即值变量)和可变变量(不推荐使用)
val a = 100
var x = 200
x = 300
下面的语句等价:
val y: Int = 10;
val y = 10
语句结尾的分号是可选的。
函数中最后一句表达式的结果就是函数的返回值
定义函数
返回值是Int型
def add(firstInput: Int, secondInput: Int): Int = {
val sum = firstInput + secondInput
return sum
}
简洁的版本
返回值类型可以省略,但不建议省略;函数体只有一句表达式时,可以省略花括号
def add(firstInput: Int, secondInput: Int): Int = firstInput + secondInput
方法
和函数很像,但是属于object,和函数的唯一区别是,他能访问object的变量
局部函数
定义在函数或方法内的函数叫局部函数,他能访问封闭他的那个函数的变量和输入参数
高阶函数
函数b是函数a的一个输入参数,那么函数a就是高阶函数。类似的,还有高阶方法。
参数f是一个函数,他有一个int型输入参数,Long型返回值
def encode(n: Int, f: (Int) => Long): Long = {
val x = n * 10
f(x)
}
匿名函数function literals
(x: Int) => x + 100 就是一个匿名函数,x是输入参数,下面是应用场景
val code = encode(10, (x: Int) => x + 100)
闭包Closures
匿名函数的一种,他的函数体中使用了非局部变量、非输入参数。
下面的(n: Int) => (n * seed) 就是一个闭包,也是一个匿名函数,它使用了一个变量seed
def encodeWithSeed(num: Int, seed: Int): Long = {
def encode(x: Int, func: (Int) => Int): Long = {
val y = x + 1000
func(y)
}
val result = encode(num, (n: Int) => (n * seed))
result
}
类class
相比java,他把类名定义和构造方法结合在一起了
class Car(mk: String, ml: String, cr: String) {
val make = mk
val model = ml
var color = cr
def repaint(newColor: String) = {
color = newColor
}
}
实例化
val mustang = new Car("Ford", "Mustang", "Red")
单例类
这个类只能实例化一次,只有一个对象
object DatabaseConnection {
def open(name: String): Int = {
...
}
def read (streamId: Int): Array[Byte] = {
...
}
def close (): Unit = {
...
}
}
样例类case class
Case Class(样例类)进行模式匹配(类似switch case,这也是名字的由来),相对于java中的javaBean,用来封装消息,而scala不需要我们手动写get和set方法,会默认把参数设置成val。
case class Message(from: String, to: String, content: String)
scala自动给他创建了同名的工厂方法,实例化就不用写new了
val request = Message("harry", "sam", "fight")
他的所有输入参数自动都是val 不可变的,且是外部类可以直接访问的(类似java的public的)
scala还自动给case class添加了toString,hashCode,equals,copy方法,所以他自动支持序列化
它自动支持模式匹配
模式匹配
用match case替代了switch case语句,每一个case自动有break,所以只可能执行一个case,都不匹配的话就匹配case _
def f(x: Int, y: Int, operator: String): Double = {
operator match {
case "+" => x + y
case "-" => x - y
case "*" => x * y
case "/" => x / y.toDouble
case _ => 0
}
}
操作符operator
每一个操作符都是一个方法,使用操作符等同于调用方法
val z = x+y
val z = x.+(y)
以上两句作用相同
trait
Scala Trait(特征) 类似 Java 的接口+抽象类,可以包括方法和变量,一个类可以继承多个trait(这点像接口)
trait Shape {
def area(): Int
}
class Square(length: Int) extends Shape {
def area = length * length
}
class Rectangle(length: Int, width: Int) extends Shape {
def area = length * width
}
val square = new Square(10)
val area = square.area
元组tuple:可以包含不同类型的元素,不可修改
val twoElements = ("10", true)
val threeElements = ("10", "harry", true)
val first = threeElements._1
val second = threeElements._2
val third = threeElements._3
集合比如list、array,只能放置相同类型的元素
Option选项
Scala Option(选项)类型用来表示一个值是可选的(有值或无值)。
Option[T] 是一个类型为 T 的可选值的容器: 如果值存在, Option[T] 就是一个 Some[T] ,如果不存在, Option[T] 就是对象 None 。
避免使用了返回null的函数,处理返回值时报出空指针异常。
def colorCode(color: String): Option[Int] = {
color match {
case "red" => Some(1)
case "blue" => Some(2)
case "green" => Some(3)
case _ => None
}
}
val code = colorCode("orange")
code match {
case Some(c) => println("code for orange is: " + c)
case None => println("code not defined for orange")
}
集合Collection分三类:序列Sequence、set,映射map,所有其他集合都是这三种集合的子类
序列sequence:元素有特定的顺序,可以通过下标访问元素
数组Array:元素可修改,数组长度不可变
val arr = Array(10, 20, 30, 40)
arr(0) = 50
val first = arr(0)
列表List:不可更改,
val xs = List(10,20,30,40)
val ys = (1 to 100).toList
val zs = someArray.toList
head方法:访问第一个元素;tail:访问除了第一个元素之外的所有元素
向量Vector
val v1 = Vector(0, 10, 20, 30, 40)
val v2 = v1 :+ 50
val v3 = v2 :+ 60
val v4 = v3(4)
val v5 = v3(5)
set:元素无序,不能用下标访问,元素无重复
val fruits = Set("apple", "orange", "pear", "banana")
映射Map
val capitals = Map("USA" -> "Washington D.C.", "UK" -> "London", "India" -> "New Delhi")
val indiaCapital = capitals("India")
集合类的高阶方法:这是scala集合类真正强大的地方
映射map方法:返回集合的元素数量和源数据集合的元素数量一致
val xs = List(1, 2, 3, 4)
val ys = xs.map((x: Int) => x * 10.0)
以下语句作用相同:
val ys = xs.map((x: Int) => x * 10.0)
val ys = xs.map{(x: Int) => x * 10.0} map函数只有一个输入参数,所以小括号可以换成花括号
val ys = xs map {(x: Int) => x * 10.0} 操作符调用方式可以和方法调用方式混用
val ys = xs map {x => x * 10.0} scala可以猜测集合中元素的类型
val ys = xs map (x => x * 10.0)
val ys = xs map (_ * 10.0) x在匿名函数中只用了一次,所以括号中可以只写匿名函数体
val ys = xs map {_ * 10.0} _表示匿名函数的输入参数,在这里表示集合xs的元素
扁平化flatMap:输入参数是集合,输出参数是集合的集合,每一个输入参数的集合元素会变成一个集合,但是返回值是一级的集合,即二级集合的扁平化
val line = "Scala is fun"
val SingleSpace = " "
val words = line.split(SingleSpace)
val arrayOfChars = words flatMap {_.toList}
结果是arrayOfChars: Array[Char] = Array(S, c, a, l, a, i, s, f, u, n)
过滤filter:只有执行匿名函数返回true的元素才能通过过滤器
val xs = (1 to 100).toList
val even = xs filter {_ %2 == 0}
foreach:对每个元素执行操作,类似map,但是map返回一个集合,foreach什么都不返回,就像数据库中函数和存储过程的关系
val words = "Scala is fun".split(" ")
words.foreach(println)
reduce:压缩、简化
val product = xs reduce {(x,y) => x * y}
val max = xs reduce {(x,y) => if (x > y) x else y}
一个独立的scala程序:必须有一个单例对象,这个单例对象包含一个没有返回值的main方法
object HelloWorld {
def main(args: Array[String]): Unit = {
println("Hello World!")
}
}
MapReduce的map和reduce都参考了函数式编程中的map和reduce的思想,scala本身支持函数式编程,所以也包含map和reduce