您的位置:首页 > 编程语言

scala基础

2017-11-18 19:08 127 查看
翻译自《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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息