scala基础

来源:互联网 发布:什么是软件危机 编辑:程序博客网 时间:2024/05/20 04:13
翻译自《big data analytics with spark》第二章Programming in Scala

scala基础
虽然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


转自:http://blog.csdn.net/matthewei6/article/details/78570522