目录
相关知识
Scala即可伸缩的语言(Scalable Language),是一种多范式的编程语言,类似于java的编程,设计初衷是要集成面向对象编程和函数式编程的各种特性。
1.Scala的特点
(1)Scala具有更广泛意义上的类重用。Scala允许定义新类的时候重用“一个类中新增的成员定义(即相较于其父类的差异之处)”。
(2)Scala还包含了若干函数式语言的关键概念,包括高阶函数(Higher-Order Function)、局部套用(Currying)、嵌套函数(Nested Function)、序列解读(Sequence Comprehensions)等等。
(3)Scala是静态类型的,这就允许它提供泛型类、内部类、甚至多态方法(Polymorphic Method)。
(4)Scala可以与Java互操作。它用scalac这个编译器把源文件编译成Java的class文件(即在JVM上运行的字节码)。你可以从Scala中调用所有的Java类库,也同样可以从Java应用程序中调用Scala的代码。
系统环境
jdk-7u75-linux-x64
scala-2.10.4
hadoop-2.6.0-cdh5.4.5
scala语法
1.启动Scala。
1.在Linux命令行任意目录下,启动Scala。
scala
2.Scala 变量
在 Scala 中,使用关键词 “var” 声明变量,使用关键词 “val” 声明常量。在 Scala 中声明变量和常量不一定要指明数据类型,在没有指明数据类型的情况下,其数据类型是通过变量或常量的初始值推断出来的。所以,如果在没有指明数据类型的情况下声明变量或常量必须要给出其初始值,否则将会报错。(备注:val 变量的值只能初始化一次,再次赋值会发生错误,var 和 Java 的变量相同,可以随时修改。val 是函数式编程的风格,变量一旦赋值就不要再做修改。)
var x:Int=10
var y=3.14
var s="hello,world"
s="hello,scala"
val str="hello,world"
str="hello,scala"
基本运算
3.算术运算
1. 1+2
2. 2*3-5/2
3. 7%3
4. 7/3
4.关系运算
5.逻辑运算
6.赋值运算符
(备注:Scala没有提供++和–的预算符,println 是 Scala 预定义导入的标准输出函数,所以可以直接使用)
7.运算符重载
:Scala允许方法调用形式a.fun(b)简写为a fun b。(字符串的+运算实际上就是调用了+方法,从而使得运算符被重载,此外to运算可以生成一个区间集合)
8.分支语句
循环语句
9.while循环
10.for循环
:Scala的for循环与Java增强型for循环类似,基本形式是for a <- 集合,a相当于集合的通项元素,用于遍历集合,<-箭头符号类似于Java增强型for循环的冒号,<-表示生成器。(备注:Scala在for循环中对循环变量i的赋值用了“<-”符号,1 to 100指定了一个范围)
在scala中还有一个和上面的to关键字有类似作用的关键字until,它的不同之处在于不包括最后一个元素。
函数
:在scala中,函数与变量同等地位,函数的定义可以单独定义,可以不依赖于类、接口或者object,而且独立存在,独立使用,并且可以赋值给变量。Spark当中的计算都是用scala函数式编程来做。
11.库函数
(在Scala中,_字符是“通配符”,类似Java中的*)
12.自定义函数
:函数的定义用 def 开始。每个函数参数后面必须带前缀冒号的类型标注,因为 Scala 编译器没办法推断函数参数类型。Scala 函数定义格式如下:
1. def functionName ([参数列表]) : [return type] = {
2. function body
3. return [expr]
4. }
现定义一个求解最大值的函数,用于求两数的最大值。(备注:Scala函数可以没有return 语句,默认返回最后一个值)
如果函数的参数在函数体内只出现一次,则可以使用下划线代替
13.可变参数
:Scala允许指定函数的最后一个参数可重复。(备注:如果函数没有返回值,可以返回为 Unit,这个类似于 Java 的 void)
1. def prints(args:String*)={
2. for(arg <- args){
3. println(arg)
4. }
5. }
6. prints("aa","bb","cc")
14.函数赋值
可以将一个函数赋值给一个变量:val 变量名 = 函数名+空格+_,这里函数名后面必须要有空格,表明是函数的原型。
1. def max(x: Int, y: Int): Int = if(x < y) y else x
2. val fmax=max _
3. fmax(3,5)
15.匿名函数
:匿名函数格式:val 变量名 = (参数:类型) => 函数体
1. var increase = (x: Int) => x + 1
2. var n=1;
3. println(increase(n))
16.高阶函数
:可以使用其他函数作为参数,或者使用函数作为输出结果。
1. import scala.math._
2.
3. def valueFor(f:(Double)=>Double,value:Double)={
4. f(value)
5. }
6. valueFor(ceil _,0.25)
7. valueFor(sqrt _,0.25)
map方法接受一个函数参数,将它应用到数组中的每个元素,返回新的数组。
1. import scala.math._
2. val num = 3.14
3. val func = ceil _
4. val array = Array(1.0,3.14,4).map(func)
5. for(i<-array)print(i+" ")
17.闭包
:可以简单的认为是可以访问一个函数里面局部变量的另外一个函数。
1. var factor = 3
2. val multiplier = (i:Int) => i * factor
3. println(multiplier(1))
4. println(multiplier(2))
18.柯里化(Currying)
柯里化函数是将原来接收两个参数的函数转变成新的接收一个参数的函数过程。新函数返回一个以原有第二个参数作为参数的函数。
1. def mul(x:Int)=(y:Int)=>x*y
2. mul(2)(3)
3. (mul(2))(3)
Scala可以简写柯里化函数,如下面例子所示:
1. def strcat(s1: String)(s2: String) = s1 + s2
2. strcat("hello")("world")
字符数组
19.字符串
1. val msg = "hello"
2. println(msg.length)
3. println(msg.charAt(0))
4. println(msg.compareTo("hi"))
5. println(msg.equals("hello"))
6. val s=msg+",spark"
7. println(s.substring(6))
20.数组Array
1. var a1 = Array("QQ", "Baidu", "Google")
2. for(x<-a1)println(x)
3. a1.foreach(x => println(x))
4. a1.foreach(println(_))
5. a1.foreach(println)
1. var a2 =new Array[String](3)
2. a2(0)="hello"
3. a2(1)="spark"
4. a2(2)="!"
5. println(a2(1))
21.数组ArrayBuffer
:Array是定长数组,而ArrayBuffer是可变数组。ArrayBuffer对应于Java中的ArrayList。
+=表示在ArrayBuffer尾部添加元素,尾部添加多个元素时用括号包起来。
++=表示追加任何集合
toArray表示将ArrayBuffer转换为Array
toArrayBuffer表示将Array转换为ArrayBuffer
1. import scala.collection.mutable.ArrayBuffer
2. val ab=ArrayBuffer[Int]()
3. ab += 1
4. ab += (2,3,5)
5. val array=Array(7,11,17)
6. ab ++= array
7. ab.foreach(println)
8. //转换成数组
9. val a1=ab.toArray
10. val buffer=a1.toBuffer
22.列表List
:Scala 列表类似于数组,它们所有元素的类型都相同,但是它们也有所不同:列表是不可变的,值一旦被定义了就不能改变,其次列表具有递归的结构(也就是链接表结构)而数组不是。列表的元素类型 T 可以写成 List[T]。
Scala的List,scala.List,不同于Java的java.util.List,总是不可变的(而Java的List可变)。更通常的说法,Scala的List是设计给函数式风格的编程用的。
1. val fruit: List[String] = List("apples", "oranges", "pears")
2. //通过索引,取第一个无素
3. println(fruit(0))
4. //取第一个无素
5. println(fruit.head)
6. //取除第一个元素外剩余的元素,返回的是列表
7. println(fruit.tail)
8. //取列表最后一个元素
9. fruit.last
10. //判断是否为空
11. println(fruit.isEmpty)
12. //列表元素倒置
13. fruit.reverse
14. //获取前n个元素
15. fruit.take(2)
16. //取列表的长
17. fruit.length
18. //遍历每个元素
19. fruit.foreach(x => println(x))
可以使用 ::运算符或 List.:😦) 方法或 List.concat() 方法来连接两个或多个列表
1. val newFruit1="bananas"::fruit
2. val newFruit2=List.concat(List("bananas"),fruit )
23.元组
:与列表一样,元组也是不可变的,但与列表不同,元组可以同时包含不同类型的元素。一旦你已经实例化了一个元组,你可以用点号,下划线和一个基于1的元素索引访问它。
1. val pair =(40,"Foo")
2. println(pair)
3. println(pair._1)
4. println(pair._2)
24. 映射 Map
:是一组键/值对的对象。 任何值都可以根据键来进行检索。键在映射中是唯一的,但值不一定是唯一的。映射也称为哈希表。映射有两种,不可变的和可变的。可变对象和不可变对象之间的区别在于,当对象不可变时,对象本身无法更改。
1. import scala.collection.mutable.Map
2. var map = Map(1 -> "a", 2 -> "b", 3 -> "c")
3. println(map.keys)
4. println(map.values)
5. println(map.isEmpty)
6. map += (4 -> "d")
7. map.foreach(value => print(value + " "))
将函数映射到集合
25.map函数的用法
:将一个函数传入map中,然后利用传入的这个函数,将集合中的每个元素处理,并将处理后的结果返回。
1. val nums=List(1,2,3,4)
2. nums.map(x=>2+x)
3. nums.map(_+1)
26.flatMap与map唯一不一样
的地方就是传入的函数在处理完后返回值必须是List,其实这也不难理解,既然是flatMap,那除了map以外必然还有flat的操作,所以需要返回值是List才能执行flat这一步。
1. val data = List("Hadoop","Java","Spark")
2. println(data.flatMap(_.toList))
参考资料:子雨大数据之Spark入门教程(Scala版)
http://dblab.xmu.edu.cn/blog/spark/