Actor 实现在Scala不同进程间,进行消息通信(同步消息、异步消息)
新Scala API里面,不包含Actor
===============Scala语言的常用集合=================================
一、可变集合和不可变集合
二、列表:不可变列表(List)、可变列表(LinkedList)
import scala.collection.mutable
def test5() = {
val peoples = Map("john" -> 19, "Tracy" -> 18, "Lily" -> 20) //不可变
// people.put("lucy",15) 会出错,因为是不可变集合。
//遍历方式1
for(p <- peoples) {
print(p + " ") // (john,19) (Tracy,18) (Lily,20)
}
//遍历方式2
peoples.foreach(x => {val (k, v) = x; print(k + ":" + v + " ")}) //john:19 Tracy:18 Lily:20
//遍历方式3
peoples.foreach ({ case(k, v) => print(s"key: $k, value: $v ")})
//key: john, value: 19 key: Tracy, value: 18 key: Lily, value: 20
}
test5()
val peoples = Map("john" -> 19, "Tracy" -> 18, "Lily" -> 20) //不可变
def test6() = {
val map = new mutable.HashMap[String, Int]()
map.put("john", 19) // 因为是可变集合,所以可以put
map.put("Tracy", 18)
map.contains("Lily") //false
val res = getSome(map.get("john"))
println(res) //Some(19)
}
def getSome(x:Option[Int]) : Any = {
x match {
case Some(s) => s
case None => "None"
}
}
/*
特意将ArrayBuffer单独拎出来,是因为ArrayBuffer类似于Java中的ArrayList。
而ArrayList在Java中是用得非常多的一种集合类。
ArrayBuffer与ArrayList不一样的地方在于,ArrayBuffer的长度是可变的。
与Array一样,元素有先后之分,可以重复,可以随机访问,但是插入的效率不高。
*/
def test() = {
val arrayBuffer = new mutable.ArrayBuffer[Int]()
arrayBuffer.append(1) //后面添加元素
arrayBuffer.append(2)
arrayBuffer += 3 //后面添加元素
4 +=: arrayBuffer //前面添加元素
}
三、序列:Vector、Range
//Queue队列
//immutable queue 不可变队列
var queue=scala.collection.immutable.Queue(1,2,3)
//queue: scala.collection.immutable.Queue[Int] = Queue(1, 2, 3)
//出队
queue.dequeue
//res38: (Int, scala.collection.immutable.Queue[Int]) = (1,Queue(2, 3))
//入队
queue.enqueue(4)
//res40: scala.collection.immutable.Queue[Int] = Queue(1, 2, 3, 4)
//mutable queue 可变队列
var queue2=scala.collection.mutable.Queue(1,2,3,4,5)
//queue: scala.collection.mutable.Queue[Int] = Queue(1, 2, 3, 4, 5)
//入队操作
queue2 += 5
//res43: scala.collection.mutable.Queue[Int] = Queue(1, 2, 3, 4, 5, 5)
//集合方式
queue2 ++= List(6,7,8)
//res45: scala.collection.mutable.Queue[Int] = Queue(1, 2, 3, 4, 5, 5, 6, 7, 8)
四、集(Set):不重复元素的集合
import scala.collection.{immutable, mutable}
// 可以在任何地方引入 可变集合
/*
Seq主要由两部分组成:IndexedSeq与LinearSeq。
现在我们简单看下这两种类型。
首先看IndexedSeq,
很容易看出来这种类型的主要访问方式是通过索引,
默认的实现方式为vector。
*/
def test() = {
val x = IndexedSeq(1,2,3)
println(x.getClass)
println(x(0))
val y = Range(1, 5)
println(y)
}
//LinearSeq,主要的区别在于其被分为头与尾两部分。
// 其中,头是容器内的第一个元素,
// 尾是除了头元素以外剩余的其他所有元素。
// LinearSeq默认的实现是List。
def test2() = {
val x = collection.immutable.LinearSeq("a", "b", "c")
val head = x.head
println(s"head is: $head")
val y = x.tail
println(s"tail of y is: $y")
}
//遇到了HashSet方法不存在的错误;这个错误发生在运行阶段,
// 具体错误信息如下:NoSuchMethodError: scala.collection.immutable.HashSet
//问题是由于scala版本兼容性导致(我的运行环境是 spark1.3/scala 2.11);
// 最后用 scala 2.10版替换掉2.11版,问题得到了解决。
def test3() = {
val x = immutable.HashSet[String]("a","c","b")
//x.add("d")无法使用,因为是不可变集合,没有add方法。
val y = x + "d" + "f" // 增加新的元素,生成一个新的集合
val z = y - "a" // 删除一个元素,生成一个新的集合
val a = Set(1,2,3)
val b = Set(1,4,5)
val c = a ++ b // 生成一个新的集合,增加集合
val d = a -- b // 生成一个新的集合,去除集合
val e = a & b // 与操作
val f = a | b // 或操作
val set = Set(1,2,3)
println(set.getClass.getName) //
println(set.exists(_ % 2 == 0)) //true
println(set.drop(1)) //Set(2,3) 表示从前往后删除元素的个数
}
def test4() = {
val x = new mutable.HashSet[String]()
x += "a" // 添加一个新的元素。注意此时没有生成一个新的集合
x.add("d") //因为是可变集合,所以有add方法
x ++= Set("b", "c") // 添加一个新的集合
x.foreach(each => println(each))
x -= "b" // 删除一个元素
println()
x.foreach(each => println(each))
println()
val flag = x.contains("a") // 是否包含元素
println(flag)
var mutableSet = new mutable.HashSet[Int]() //Set(1,2,3)
mutableSet=mutable.HashSet[Int](1,2,3)
println(mutableSet.getClass.getName) // scala.collection.mutable.HashSet
mutableSet.add(4)
mutableSet.remove(1)
mutableSet += 5
mutableSet -= 2
println(mutableSet) // Set(5, 3, 4)
val another = mutableSet.toSet
println(another.getClass.getName) // scala.collection.immutable.Set
}
五、模式匹配: Java中switch语句
1、基本用法
2、守卫:在模式匹配中使用if语句
3、模式匹配的变量
4、类型模式匹配
5、匹配数组和列表
===========示例代码============
def fileLines(file: java.io.File) =
scala.io.Source.fromFile(file).getLines.toList
def grep(pattern:String) =
for (
file <- (new java.io.File("E:\\scalaIO.txt")).listFiles if file.getName.endsWith("txt");
line <- fileLines(file) if line.trim.contains(pattern)
) yield line.trim
for(i <- grep("s"))println("打印 "+i)
var sign =0
var ch1='_'
ch1 match{
case '+' => sign=1
case '-' => sign= -1
case '_' => sign=0 //其他的值
}
//2守卫 匹配所有的数字
var ch2 ='6'
var digit:Int = -1
ch2 match{
case '+' => sign=1
case '-' => sign= -1
case _ if Character.isDigit(ch2) => digit =Character.digit(ch2,10)
case '_' => sign=0
}
//3 模式匹配变量
var v3="hello world"
v3(7) match{
case '+' => sign=1
case '-' => sign= -1
case ch=> println("这是字符是"+ch)//ch变量代表值
}
//4 类型模式匹配
var v4:Any =100
v4 match{
case x:Int => println("这是整数")
case s:String => println("这是字符串")
case _ => println("其他类型")
}
//匹配数组和列表
var v5 =Array(1,2,3)
v5 match{
case Array(0) => println("数组里没有元素")
case Array(x,y) => println("数组中有两个元素" +(x+y))
case Array(x,y,z) => println("数组中有3个元素" +(x+y+z))
case Array(x,_*) => println("数组中有3个以上的元素" )
}
var v6=List(1,2,3)
v6 match{
case List(0) => println("列表里没有元素")
case List(x,y) => println("列表里有2个元素")
case List(x,y,z) => println("列表里有3元素")
case List(x,_*) => println("列表里有3个以上的元素")
}
object test12 {
/*yield 关键字在循环中生成返回结果
每次循环会把值保留,执行完后会把所有值转换为数组Array[File]类型并返回
*/
def main(args: Array[String]): Unit = {
println(getFile(0))
}
def getFile =
for{
file <- (new java.io.File(".")).listFiles if file.getName.endsWith("iml")
}yield file
}
/*Array数组操作
定长数组Array 不可增加
Scala中的Array是以Java中的Array方式实现的 */
var arr = 0 until 5
//scala.collection.immutable.Range = Range 0 until 5
val arr1 = new Array[Int](10)
//复杂对象类型的数组初使化值为null,数值型被初使化为0
val arr2 = Array("aaa","bbb")
//定义一个数组同时赋值,这种调用方式是调用其apply方法进行数组创建操作的
arr2(1)="test"
//数组元素赋值,不同于Java,这里index的指定是用小扩号。
arr2.update(1,"test2")
arr2.foreach(println)
//更新值
import scala.collection.mutable.ArrayBuffer
/*
变长数组ArrayBuffer
scala.collection.mutable.ArrayBuffer
*/
var arr=ArrayBuffer[String]()
arr+="Hello"
arr+=("Hello","Scala")
//+= 在尾部添加元素
arr.insert(1,"test1" )
//arr.insertAll(3,arr)
arr.foreach(println)
arr.insertAll(3,arr)
//在指定位置插入数据
arr.remove(0,2)
//从索引0开始,删除2个元素
arr++=Array("hello","test")
arr++=List("value1","value2")
//++=用于向数组中追加内容,++=右侧可以是任何集合
arr.trimStart(2)
//删除前面2个元素
arr.trimEnd(2)
//删除未尾2个元素
arr.toArray
//转换ArrayBuffer to Array
arr.toBuffer
//转换Array to ArrayBuffer
//遍历数组
//to 方式
for(i ← 0 to arr.length-1)println(arr(i))
//until方式
for(i ← 0 until arr.length)println(arr(i))
//foreach方式
for(i ← arr)print("\t"+i)
//指定步长
for(i← 0 until (arr.length,2)) print("\t"+arr(i))
for(i← (0 to (arr.length-1,2))) print("\t"+arr(i))
//倒序输出
for(i ← (0 until arr.length).reverse) print("\t"+arr(i))
for(i ← (0 to arr.length -1).reverse) print("\t"+arr(i))
for(i ← arr.reverse) print("\t"+i)
//yield返回新的数组
var arr2 = for(i ← arr) yield i+"test"
/*原数组不变
*BufferArray转换后产生的仍然是BufferArray
*Array转换后产生的仍然是Array */
//数组求和,最大值,最小值,格式化输出,过滤掉小于3数据
val intArr = Array(1,2,3,4,5)
println(intArr.sum)
println(intArr.max)
println(intArr.min)
println(intArr.mkString)
println(intArr mkString ",")
println(intArr.mkString("(",",",")"))
println(intArr.dropWhile(_<3) mkString ",")
//多维数组
var multiArr = Array(Array(1,2,3),Array(4,5,6))
println(multiArr(1)(2))
for (elem ← multiArr) {println(elem mkString(","))}
//List的定义
val cars = List("bmw","volvo")
val cars2 = List.apply("bmw","volvo")
val nums2 = List(1,2,3,4,5,6,7,7,8)
var cars3:List[Object]=List("BMW","Volvo")
var list= List()
var cars4:List[String]=List()
//采用 :: 及Nil进行列表构建
val nums5 = 1 :: (2 :: (3:: (4::Nil)))
//相等于
val nums6 = List(1, 2, 3, 4)
//相等于
val nums = 1::2::3::4::Nil
//多重List
val cars5=List(List("BMW","200万","red"),List("BYD","20万","white"))
/*list一旦被创建,其值不能被改变
*list具有递归结构(Recursive Structure),例如链表结构
*List类型和其它集合类型一样,它具有协变性(Covariant),即对于类型S和T,如果S是T的子类型,则List[S]也是List[T]的子类型
*空的List,其类型为Nothing,Nothing在Scala的继承层次中的最低层,即Nothing是任何Scala其它类型如String,Object等的子类
* :: 操作符的优先级是从右往左的*/
//list常用操作
//判断是否为空
cars.isEmpty
//取第一个元素
cars.head
//取第一个元素外的元素列表
print("取第一个元素外的元素列表 "+cars.tail)
cars.reverse.init
//init取最后一个元素外的元素列表
cars.init
cars.reverse.tail
//取最后一个
var a =cars.last
//取第二个元素
cars.tail.head
//取倒数第二个元素
println("取倒数第二个元素"+cars.init.last)
//元素倒置
cars.reverse
//丢弃前N个元素,返回元素列表
cars drop 1
//获取前几个元素列表
cars take 2
cars.take(2)
//将列表进行分割,从Index N的位置进行分割,返回前后两个元素列表,位置N算后面的元素列表
cars.splitAt(1)
(cars.take(1),cars.drop(1))
//zip 返回的是List类型的元组(Tuple)
val arr = List("1","6","3","5","9")
//arr: List[String] = List(1, 6, 3, 5, 9)
val num = List(1,6,3,5,9)
//num: List[Int] = List(1, 6, 3, 5, 9)
//数组 与 数组 zip操作 产生 元组
arr zip num
//res99: List[(String, Int)] = List((1,1), (6,6), (3,3), (5,5), (9,9))
//List连接操作 :::
List(1,2):::List(3,4)
//res35: List[Int] = List(1, 2, 3, 4)
// list相等判断
val arr20 = List(1,6,3,5,9)
val arr10 = List("1","6","3","5","9")
println(arr20 == arr10) //false
val arr21 = List("1","6","3","5","9")
val arr22= List("1","6","3","5","9")
println(arr22 == arr21) //true
//range方法,构建某一值范围内的List
val nums01 = List.range(2,9)
//range主法,指定步长N,范围不存在的返回空List
val nums02 = List.range(2,100, 5)
val nums03 = List.range(100,20, -5)
//flatten,将列表平滑成第一个元素
List(List("aaa","bbb"),List("111","222")).flatten
//concat列表链接
List.concat(List("aaa","bbb"),List("111","222"))
object test16 {
//插入排序算法
def sort(xs:List[Int]) :List[Int] ={
if(xs.isEmpty) Nil
else insert(xs.head, sort(xs.tail))
}
def insert(x:Int, xs:List[Int]) :List[Int] ={
if(xs.isEmpty || x<= xs.head) x:: xs
else xs.head :: insert(x,xs.tail)
}
def main(args: Array[String]): Unit = {
val arr = List(1,6,3,5,9)
arr.foreach(print)
println(" ")
var arr2= test16.sort(arr)
arr2.foreach(print)
}
}
import scala.collection.mutable
//Set 不可重复,无序的集合
//如果需要按添加顺序排序,可以使用LinkedHashSet实现
val set = Set(1,2,3)
val mutableSet = mutable.Set(1,2,3)
val linkedhashset =mutable.LinkedHashSet(1,2,3,4,5,6,7)
print(linkedhashset.head)
//添加元i
set+5
//遍历Set
for(i ← set+7)print(i)
val map = Map(1 → "one","two" → 2,2.3 → "three")
val mutableMap = mutable.Map(1 → "one","two" → 2,2.3 → "three")
println(map)
//添加元素
println(map.+(4 → "four"))
//删除元素
println(map.-("tow"))
//遍历map
for(i<-map)println(i+"\t"+i._1+"\t"+i._2)
map.foreach(e=>{
val (k,v)=e
println(k,v) //通过模式匹配获取元组内容
println(e._1,e._2) //直接访问元组内容
})
//mutable map可以使用put添加元素
val mutableMap2 = mutable.Map(1 → "one","two" → 2,2.3 → "three")
mutableMap2.put("four",4)
//判断key是不存在
map.contains(1)
map.get("key")
map.get(1)
六、样本类(case class): 为了更好的支持模式匹配
在Spark SQL中,使用样本类定义表(DataFrame)结构(schema)
== Scala语言的高级特性(泛型)=================================
一、泛型类[T]
二、泛型函数: T:ClassTag
三、上界(upper bounds)和下界(lower bounds): 都是来规定类型的范围
1、简单的一个例子:
基本数据类型: 100 <= x <= 200 规定了x的取值范围
类型(类和对象,继承关系)
ClassA --> ClassB --> ClassC ---> ClassD
创建一个对象: ClassD <: x <: ClassB 表示x的取值只能是:ClassB ClassC ClassD
下界 上界
2、举例(上界)
3、上界:写法: S <: T 表示S的类型必须是T的子类或者本身
下界:写法: U >: T 表示U的类型必须是T的父类或者本身
4、再举一个例子: 拼加两个字符串
def addTwoString[T <: String](x:T,y:T) = println(x+"****"+y)
调用一下
addTwoString("Hello","World")
再来调用一下
addTwoString(100,200) ---> 100和200是数字
希望得到:100****200
四、视图界定
1、就是类型的上界和下界,但适用范围更广
2、上界为例:写法 <%
可以接收子类和本身,还可以接收隐式转换过去的类型
def addTwoString[T <% String](x:T,y:T) = println(x+"****"+y)
(1) T的类型可以是String或者子类
(2) 还可以是可以转换成String的类型
如果定义了视图界定,一定要定义转换规则(隐式转换:就是一个函数)
implicit def intTOString(n:Int):String = {n.toString}
分析过程:scala> addTwoString(100,200)
100****200
第一步:在当前的范围内,去查找一个隐式转换规则(int ---> String):intTOString
第二步:调用intTOString把100和200转成字符串: "100" "200"
第三步:调用addTwoString拼加
五、协变和逆变
1、协变:泛型变量的值可以是本身类型或者子类的类型
2、逆变:泛型变量的值可以是本身类型或者父类的类型
六、隐式转换函数
七、隐式参数
八、隐式类
闭包
========================================================================
闭包是一个函数,返回值依赖于声明在函数外部的一个或多个变量。
如下面这段匿名的函数:
val multiplier = (i:Int) => i * 10
函数体内有一个变量 i,它作为函数的一个参数。如下面的另一段代码:
val multiplier = (i:Int) => i * factor
在 multiplier 中有两个变量:i 和 factor。其中的一个 i 是函数的形式参数,在 multiplier 函数被调用时,i 被赋予一个新的值。然而,factor不是形式参数,而是自由变量,考虑下面代码:
var factor = 3
val multiplier = (i:Int) => i * factor
这里我们引入一个自由变量 factor,这个变量定义在函数外面。
这样定义的函数变量 multiplier 成为一个"闭包",因为它引用到函数外面定义的变量,定义这个函数的过程是将这个自由变量捕获而构成一个封闭的函数。
========================================================================
柯里化函数:增加函数调用可读性
========================================================================
柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数, 并且返回接受余下的参数而且返回结果的新函数的技术。
分析:def add1(x:Int)(y:Int) = x + y 调用过程(执行过程)
调用:add1(1)(2)
第一步:add1(1) ====> 返回一个新的函数:x,接收一个参数(y:Int)
举例:访问数据库,执行查询
def accessOracleTable(props:Propertis)(table:String)(sql:String)
第一步:accessOracleTable(props:Propertis) _ _ ----> 返回一个新的函数step1:接收的参数:(table:String)(sql:String)
第二步:step1("emp") _ ----> 返回一个新的函数step2:接收的参数:(sql:String)
第三步:step2("select **** from ***")