scala集合
不可变集合:import scala.collection.immutable._
可变集合:import scala.collection.mutable._
1、可变集合、不可变集合-----(Map)
scala> //不可变集合
scala> val math = scala.collection.immutable.Map("Tom"->80,"Mary"->90,"Mike"->85)
math: scala.collection.immutable.Map[String,Int] = Map(Tom -> 80, Mary -> 90, Mike -> 85)
scala> //可变集合
scala> val chinese = scala.collection.mutable.Map("Tom"->80,"Mary"->90,"Mike"->85)
chinese: scala.collection.mutable.Map[String,Int] = Map(Mike -> 85, Tom -> 80, Mary -> 90)
scala> //集合的操作
scala> //1、获 取集合中的值
scala> chinese.get("Mary")
res2: Option[Int] = Some(90)
scala> chinese("Mary")
res3: Int = 90
scala> //2、判断是否存在这个key
scala> chinese("Bob")
java.util.NoSuchElementException: key not found: Bob
at scala.collection.MapLike$class.default(MapLike.scala:228)
at scala.collection.AbstractMap.default(Map.scala:59)
at scala.collection.mutable.HashMap.apply(HashMap.scala:65)
... 32 elided
scala> if(chinese.contains("Bob")){
| chinese("Bob")
| }else{
| -1
| }
res5: Int = -1
scala> //简写
scala> chinese.getOrElse("Bob")
<console>:13: error: not enough arguments for method getOrElse: (key: String, default: => B1)B1.
Unspecified value parameter default.
chinese.getOrElse("Bob")
^
scala> chinese.getOrElse("Bob",-1)
scala> //更新集合中的值:注意:必须是一个可变集合
scala> chinese("Mary")
res8: Int = 90
scala> chinese("Mary")=95
scala> chinese("Mary")
res10: Int = 95
scala> //添加新的元素
scala> chinese += "Bob" -> 88
res11: chinese.type = Map(Bob -> 88, Mike -> 85, Tom -> 80, Mary -> 95)
scala> //移除元素
scala> chinese -= "Bob"
res12: chinese.type = Map(Mike -> 85, Tom -> 80, Mary -> 95)
2、列表:不可变列表(List)\可变列表(LinkedList)
scala> //字符串列表
scala> val nameList = List("Bob","Tom","Mary")
nameList: List[String] = List(Bob, Tom, Mary)
scala> //整数列表
scala> val intList = List(1,2,3)
intList: List[Int] = List(1, 2, 3)
scala> //空列表
scala> val nullList:List[Nothing] = List()
nullList: List[Nothing] = List()
scala> //二维列表:类似二维数组
scala> //通过列表的列表来实现
scala> val dim:List[List[Int]]= List(List(1,2,3),List(10,20,30))
dim: List[List[Int]] = List(List(1, 2, 3), List(10, 20, 30))
scala> println(nameList.head+" ****** "+ nameList.tail)
Bob ****** List(Tom, Mary)
scala> //val nameList = List("Bob","Tom","Mary")
scala> //nameList.tail返回的不是最后一个元素,是:除去第一个元素后,剩下的元素
可变列表
scala> //可变列表: scala.collection.mutable.LinkedList
scala> //类似List,只是我们可以改变里面的值
scala> val myList = scala.collection.mutable.LinkedList(1,2,3,4,5)
warning: there was one deprecation warning; re-run with -deprecation for det
myList: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2, 3, 4, 5)
scala> //操作:对里面的每个元素乘以2
scala> //类似:数据库的 游标、光标()cursor
scala> //定义一个指针指向可变列表的开始
scala> var cur = myList
cur: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2, 3, 4, 5)
scala> while(cur != Nil){
| //把当前元素乘以2
| cur.elem = cur.elem*2
| //移动指针,指向下一个元素
| cur = cur.next
| }
scala> //Nil:相当于Null
scala> //查看结果
scala> println(myList)
LinkedList(2, 4, 6, 8, 10)
3、序列:
(*)数据库中也有序列:Sequence
以Oracle为例: 创建序列
create sequence myseq; 后面的参数可以不写
Oracle中的序列就是一个整数的数组,一般来说,作用:
(1)作为主键,实现自动的增长,类似MySQL中的auto increment
(2)可以提高性能,序列是存在于Oracle的内存中
(*)Scala中:常用的: Vector和Range
scala> //Vector是一个带下标的序列
scala> val v = Vector(1,2,3,4,5,6)
v: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3, 4, 5, 6)
scala> //属于immutable包下,是一个不可变的
scala> //Range: 是一个整数的序列
scala> //第一种写法
scala> println(Range(0,5))
Range(0, 1, 2, 3, 4)
scala> //第二种写法
scala> println(0 until 5)
Range(0, 1, 2, 3, 4)
scala> //第三种写法
scala> println(0 to 4)
Range(0, 1, 2, 3, 4)
scala> //两个Range可以相加
scala> ('0' to '9') ++ ('A' to 'Z')
res20: scala.collection.immutable.IndexedSeq[Char] = Vector(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C,
scala> // 把Range转成List
scala> 1 to 5 toList
warning: there was one feature warning; re-run with -feature for details
res21: List[Int] = List(1, 2, 3, 4, 5)
scala>
4、集(Set):不重复的元素的集合,默认是HashSet
scala> //创建一个Set
scala> var s1 = Set(1,2,10,8)
s1: scala.collection.immutable.Set[Int] = Set(1, 2, 10, 8)
scala> //往s1中添加元素:重复的 不重复的
scala> s1 + 10
res22: scala.collection.immutable.Set[Int] = Set(1, 2, 10, 8)
scala> s1 + 100
res23: scala.collection.immutable.Set[Int] = Set(10, 1, 2, 8, 100)
scala> //创建一个课排序的Set
scala> var s2 = scala.collection.mutable.SortedSet(1,2,3,10,8)
s2: scala.collection.mutable.SortedSet[Int] = TreeSet(1, 2, 3, 8, 10)
scala> //参考一下讲义
如果在SQL中执行集合运算,是有要求的!!!!
select A,B,C,D from ****
union
select X,Y,Z from ****
上面的语法是错的,不能执行集合运算
(*)参与运算的各个集合select,必须要列数和列的类型一致
5、模式匹配:相当于Java中,switch..case语句,但是功能更强大
// 1.相当于switch case
var sign = 0
var ch = '-'
ch match {
case '+' => sign = 1
case '-' => sign = -1
case _ => sign = 0
}
println(sign)
// 2.scala的守卫,匹配某种类型的所有值
// 匹配所有数字
var ch2 = '6'
var digit: Int = -1
ch2 match {
case '+' => println("this is +")
case '-' => println("this is -")
// 10表示十进制
case _ if Character.isDigit(ch2) => digit = Character.digit(ch2, 10)
case _ => println("other")
}
//3.模式匹配的变量
var mystr = "hello world"
mystr(7) match {
case '+' => println("this is +")
case '-' => println("this is -")
case ch => println("this char is " + ch)
}
// 4.匹配类型,相当于java中的instanceof
// Any表示任意类型,相当于java中的object
var v: Any = 102
v match {
case x:Int => println("this is a digit")
case x:Int => println("this is a string")
case _ => println("other")
}
// 5.匹配数组和列表
var myArr = Array(1, 2, 3)
myArr match {
case Array(0) => println("only have a elem in the array")
case Array(x, y) => println("there have 2 elem in the array")
case Array(x, y, z) => println("there have 3 elem in the array")
case Array(x, _*) => println("have many elems in the array")
}
var myList = List(1, 2, 3)
myList match {
case List(0) => println("only have a elem in the List")
case List(x, y) => println("there have 2 elem in the List")
case List(x, y, z) => println("there have 3 elem in the List")
case List(x, _*) => println("have many elems in the List")
}
6、样本类:case class
定义:就是在class前,加上case关键字
class Fruit{}
case class Apple(name:String) extends Fruit
case class Banana(name:String) extends Fruit
val apple = new Apple("Apple")
val banana = new Apple("Banana")
println(apple.asInstanceOf[Fruit])
println(banana.asInstanceOf[Fruit])
val app= new Apple("Tom's Apple")
app match {
case Apple(name) => println("Apple" + name)
case Banana(name) => println("Banana" + name)
}
作用:
(1)支持模式匹配:也相当于instanceof
(2)定义Spark SQL的schema:定义Spark SQL的表(DataFrame
、DataSet
)结构
最后,终于把匿名函数看懂了:
【scala】匿名函数和闭包
1.函数的类型和值
Scala是一种纯面向对象的语言,每个值都是对象。Java是一种不全面向对象的语言。
Scala也是一种函数式语言,其函数也能当成值来使用。Java则是指令试编程。
但是Scala同时支持指令试编程和函数式编程,是两种编程方式的结合的一门语言。
在Scala中,我们可以把函数当作一个数据类型,可以像任何其他数据类型一样被传递和操作。这体现了函数式编程的核心。
我们可以像定义变量的那样去定义一个函数,因此,函数也就会和其他变量一样拥有类型和值。
def counter( value:Int ) : Int = { value + 1 }
我们定义了一个counter函数,参数为Int类型的value,返回值为Int类型,函数体实现是为value+1。
counter函数的类型为 ( Int ) => Int
箭头前,圆括号里面的为参数的类型,有多个参数依次写到圆括号中即可,(Int String)
。
当只有一个参数的时候可以省略圆括号Int => Int
箭头后,为返回值类型
counter函数的值为(value) => { value + 1}
箭头前,圆括号里面的为参数的值,多个参数依次写到圆括号中即可。我们可以在这里定义参数类型,(value:Int)=>{value+1}
箭头后,大括号里面为返回的值,当只有一条语句的时候可以省略掉大括号。(value)=> value + 1
我们知道了函数的类型和值,试试定义一个函数变量。
val num : Int = 5;
//我们照着这个例子完成函数变量的定义
val counter :(Int)=> Int = { (value) => {value+1} }
使用函数变量
println( counter(1) )
2.匿名函数
当一个函数就只用一次,我们就不需要给函数命名,这时我们就可以使用匿名函数。
我们通常把匿名函数称为“Lambda表达式”。
格式如下:(参数) => 表达式 //如果参数只有一个,圆括号可以省略
(num:Int) => num*2
我们可以直接把匿名函数放到变量中
val myNum :(Int) => Int = (num:Int) => num *2
//这里的形式和上面定义函数变量是一样的,只有一条语句的时候可以省略{}
//我们可以省略掉返回类型让语言自己判断,但是需要添加传入参数的类型
val myNum = (num:Int) => num*2
println(myNum(1))
//使用函数变量
我们需要注意,虽然Scala语言有自动推断类型机制,但是我们不能全部省略,需要有部分类型确定才能推断出省略的部分类型。
3.闭包
闭包是一个函数,返回值依赖于声明在函数外部的一个或多个变量。
val myNum = (num:Int) => num*2
//普通函数
val myNum = (num:Int) => num*a
//闭包,a为变量
我们看到闭包和普通函数的区别,闭包函数的返回值不仅根据参数num来确定,还依赖于外部的变量a
我们不能在没有定义变量a之前定义这个闭包,会提示not found value a。
正确定义闭包函数的方式
scala> var a = 10
a: Int = 10
scala> val myNum = (num:Int) => num*a //定义闭包函数前依赖的变量必须有值
myNum: Int => Int = $$Lambda$1050/1792172929@4b20aa21
scala> myNum(10)
res2: Int = 100
scala> a = 20 //当我们修改外部的a的变量值,闭包函数的返回值也跟着变化,创建出一个新的闭包
a: Int = 20
scala> myNum(10)
res3: Int = 200