Scala 语言的常用集合 高级特性 泛型 柯里化、闭包

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 ***")

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值