目录
一、数组
1、定长数组和变长数组
import scala.collection.mutable.ArrayBuffer(定长数组的包)不能再向数组中添加数据
import scala.collection.immutable.ArrayBuffer(不定长数组的包)可以向数组中添加数据
import scala.collection.mutable.ArrayBuffer
/**数组
* @create 2019-11-12 8:57
*/
object Test1 {
def main(args: Array[String]): Unit = {
var arr1 = new Array[Int](8);
println(arr1)//[I@23223dd8
//字符串输出
println(arr1.mkString(" "))//0 0 0 0 0 0 0 0
//转换为数组缓冲
println(arr1.toBuffer)//ArrayBuffer(0, 0, 0, 0, 0, 0, 0, 0)
//改变数组中的元素
val s = for (i<-arr1) yield i+2
print(s.mkString(" "))//2 2 2 2 2 2 2 2
println()
//变长数组
val arr01 = ArrayBuffer[Int](1,2,3,4)
val arr02 = new ArrayBuffer[Int]()
val arr03 = new ArrayBuffer[Int]
val ab = ArrayBuffer[Int]()
//向数组缓冲的尾部追加一个元素
ab+=1//+=追加一个元素
ab+=(2,3,4,5)//+=追加多个元素
ab++=Array(6,7)//++=追加一个数组
ab++=ArrayBuffer(8,9)//++=追加一个数组缓冲
ab.insert(3,5,5)//在下标2之后插入6,7
println(arr01)//ArrayBuffer(1, 2, 3, 4)
println(ab)//ArrayBuffer(1, 2, 3, 5, 5, 4, 5, 6, 7, 8, 9)
ab.remove(3,2)//删除位置3后面的两个元素
println(ab)//ArrayBuffer(1, 2, 3, 4, 5, 6, 7, 8, 9)
//arr3 = arr1.toBuffer//定长转变长
//arr2 = arr3.toArray//变长转定长
}
}
2、遍历数组
//初始化数组 val array = Array(1,2,4,5,8) //增强for循环 for (i<-array) println(i) //步长是2,表示偶数 for (i<-0 until (array.length,2)) print(i)
3、数组转化
//初始化数组
val array = Array(1,2,4,5,8)
//增强for循环
for (i<-array)
print(i+" ")
//步长是2,表示偶数
for (i<-0 until (array.length,2))
print(i+" ")
//to或者until会生成一个Range实例
//可使用reverse反转实例
for (i<-(0 until array.length).reverse) print(i+" ")
//使用函数迭代数组
array.foreach(print(_))
二、元组
object Test3 {
def main(args: Array[String]): Unit = {
println("111",23,3.4)
//元组的定义
val t1 = Tuple3("111",23,3.4)//一旦创建不能修改
println(t1._1)//111
//元组的遍历
for (i<-t1.productIterator)
print(i+" ")//111 23 3.4
println("*************华丽的分割线***************")
val arr = Array(("tom",88),("jerry",95));
//将对偶集合转换为映射
println(arr.toMap)//Map(tom -> 88, jerry -> 95)
//拉链操作
val scores = Array(89,90,96)
val names = Array("张三","李四","王五")
val zp = names.zip(scores)//可以将多个值绑定在一起
println(zp.mkString(" "))//(张三,89) (李四,90) (王五,96)
println(zp.toMap)//Map(张三 -> 89, 李四 -> 90, 王五 -> 96)
}
}
1、创建元组
val t1 = Tuple3("111",23,3.4)//一旦创建不能修改
2、获取元组中的值
println(t1._1)//获取元组第一个元素
3、元组的遍历
for (i<-t1.productIterator)//使用productIterator遍历
4、将对偶的集合转换成映射
arr.toMap//使用toMap方法转换映射
5、拉链操作
val zp = names.zip(scores)//可以将多个值绑定在一起
三、集合
Scala的集合有三大类:序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质
在Scala中集合有可变(mutable)和不可变(immutable)两种类型,immutable类型的集合初始化后就不能改变了(注意与val修饰的变量进行区别)
1、列表List
不可变的序列 import scala.collection.immutable._
在Scala中序列表要么为空(Nil表示空列表)要么是一个head元素加上一个tail列表。
9 :: List(5, 2) :: 操作符是将给定的头和尾创建一个新的列表
注意::: 操作符是右结合的,如9 :: 5 :: 2 :: Nil相当于 9 :: (5 :: (2 :: Nil))
2、集合Set
集是不重复元素的结合。集不保留顺序,默认是以哈希集实现。
如果想要按照已排序的顺序来访问集中的元素,可以使用SortedSet(已排序数据集),已排序的数据集是用红黑树实现的。
默认情况下,Scala 使用的是不可变集合,如果你想使用可变集合,需要引用 scala.collection.mutable.Set 包。
不可变的Set
//不可变set
val s1 = Set(1,2,3,3)
println(s1.size)//3
for (i<-s1)println(i)//1 2 3
val set1 = new HashSet[Int]()
val set2 = set1+4;
println(set2)//Set(4)
//set中元素不能重复
//向set中追加元素
val set3 = set1++Set(5,6,7)
print(set3)//Set(5, 6, 7)
//在set减去元素
val set4 = set1.-(1,2)
print(set4)//Set()
3、映射Map
Scala中的 Map 和 Java 类似,也是一个散列表,它存储的内容也是键值对 (kru-value) 映射。Scala中,有可变 Map (scala.collection.mutable.Map) 和不可变 Map (scala.collection.immutable.Map)。Scala中不可变的 Map 是有序的,可变的Map 是无序的。
默认是immutable.Map,key-value 支持Any,在Map的底层,每对key-valye 是 Tuple2
//不可变map
val map01 = Map[String,Int]("liuxing"->20,"xiayu"->22);
print(map01("xiayu"))//22
//print(map01("liuxi"))//报错:key not found: liuxi
println()
print(map01.get("xiayu"))
print(map01.getOrElse("xiayu",22))
//map01+=(("hadoop",2))//出错
//map01("james") = 23//出错
//创建可变map映射
val map02 = scala.collection.mutable.Map("liubei"->50,"guanyu"->40)
map02+=(("zhangfei",38))
map02("liubei")=45
println(map02)//Map(guanyu -> 40, liubei -> 45, zhangfei -> 38)
//向map中添加数据
map02.put("machao",35)
map02 +=(("huangzhong",60))
map02 +=("edou"->12)
println(map02)//Map(machao -> 35, guanyu -> 40, liubei -> 45, edou -> 12, huangzhong -> 60, zhangfei -> 38)
//从map中移除元素
map02 -="edou"
map02.remove("huangzhong")
println(map02)//Map(machao -> 35, guanyu -> 40, liubei -> 45, zhangfei -> 38)
//获取元素
println(map02.get("guanyu"))//Some(40)
println(map02.getOrElse("guanmen",0))//0
//遍历
for ((k,v)<-map02)
print(k+"="+v+" ")//machao=35 guanyu=40 liubei=45 zhangfei=38
map02.foreach(x=>print(x))//(machao,35)(guanyu,40)(liubei,45)(zhangfei,38)
4、队列Queue
队列数据存取符合先进先出策略
不可变队列:
object Test5 {
def main(args: Array[String]): Unit = {
//创建不可变队列
val q1 = scala.collection.immutable.Queue[Int]()
println("q1 = "+q1)//q1 = Queue()
val q2 = q1.enqueue(1)//enqueue:添加在队尾
println("q2="+q2)//q2=Queue(1)
val q3 = q2.enqueue(2)
println("q3="+q3)//q3=Queue(1, 2)
val q4 = q3.enqueue(3,4)
println("q4="+q4)//q4=Queue(1, 2, (3,4))
val q5 = q4.enqueue(List(3,4))//添加List
println("q5="+q5)//q5=Queue(1, 2, (3,4), 3, 4)
val q6 = q5.enqueue(mutable.Queue(5,6))//添加Queue
println("q6="+q6)//q6=Queue(1, 2, (3,4), 3, 4, Queue(5, 6))
val q7 = q6.drop(1)//删除队首一个元素
println("q7="+q7)//q7=Queue(2, (3,4), 3, 4, Queue(5, 6))
val q8 = q7.drop(2)//删除队首两个元素
println("q8="+q8)//q8=Queue(3, 4, Queue(5, 6))
q7.foreach(println)//遍历
val q9 = q8.head//获取队首第一个元素
println("q9="+q9)//q9=3
val q10 = q8.tail
println("q10="+q10)//q10=Queue(4, Queue(5, 6))
}
}
可变队列:
val q1 = new mutable.Queue[Int]()
println(q1)
//队列元素的追加
q1 += 1;
println(q1)
//向队列中追加list
q1 ++= List(2, 3, 4, 6)
println(q1)
//按照进入队列的顺序删除元素
q1.dequeue()
println(q1)
println(q1.head) //返回队列第一个元素
println(q1.last) //返回队列的最后一个元素
println(q1.tail) //返回除了第一个元素之外的元素
5、选项Option
在Java 里,null 是一个关键字,不是一个对象,所以对它调用任何方法都是非法的。但是这对语言设计者来说是一件令人疑惑的选择。为什么要在程序员希望返回一个对象的时候返回一个关键字呢?
为了让所有东西都是对象,也为了遵循函数式编程的习惯,Scala鼓励你在变量和函数返回值使用Option类型。在没有值的时候,使用None,这是Option的一个子类。如果有值可以引用,就使用Some来包含这个值。Some也是Option的子类。
//选项option
val m1 = Map[String, Int]("a" -> 12, "b" -> 34)
println(m1.get("a"))//返回some(12)
println(m1.get("a").get)//12
println(m1.get("ab"))//返回None
//统一的使用方式是getOrElse
println(m1.getOrElse("a", 0))//12
6、迭代器Iterator
迭代器不是一种集合,而是遍历集合的一个类。
迭代器 it 的两个基本操作是 next 和 hasNext。
调用 it.next() 会返回迭代器的下一个元素,并且更新迭代器的状态。
调用 it.hasNext() 用于检测集合中是否还有元素。
//迭代器Iterator
val iterable1 = Iterator(1,2,3,4)
while (iterable1.hasNext){
println(iterable1.next())
}
//集合类中有iterator
val it2 = List(4,3,2,1).iterator
while (it2.hasNext){
println(it2.next())
}
//使用foreach迭代
for (x<-it2)println(x)
四、常用函数
1、map、flatmap
在spark中map函数和flatMap函数是两个比较常用的函数。其中
map:对集合中每个元素进行操作, 将集合中的每一个元素映射到某一个函数。 map将一个函数应用于列表的每一个元素并且将其作为一个新的列表返回
flatMap:对集合中每个元素进行操作然后再扁平化。 flat即压扁,压平,扁平化,效果就是将集合中的每个元素的子元素映射到某个函数并返回新的集合。 flatMap应用于每个序列元素会返回包含原始列表所有序列内的元素的列表
//普通map函数
val arr = List(List("A",1),List("B",2),List("C",3))
val arr1 = arr.map(x=>x(0))
println(arr1)//List(A, B, C)
//flatten扁平化函数
var arr2= arr.flatMap(x=>List(x(0),x(1)))
println(arr2)//List(A, 1, B, 2, C, 3)
2、reduce、fold
折叠,化简:将二元函数引用于集合中的函数reduce
折叠,化简:fold
Reduce函数将上一步返回的值作为函数的第一个参数继续传递参与运算,直到list中的所有元素被遍历。
Fold函数需要一个种子值做为初始值。可以把reduce函数看作是fold函数的简化版。
//reduce 、fold
val list = List(1,3,5,7,9)
//(1,3)(4,5)(9,7)(16,9)25
println(list.reduceLeft((x:Int,y:Int)=>{print(x,y);x+y}))
//(7,9)(5,16)(3,21)(1,24)25
println(list.reduceRight((x:Int,y:Int)=>{print(x,y);x+y}))
//(9,10)(7,19)(5,26)(3,31)(1,34)35
println(list.foldRight(10)((x:Int,y:Int)=>{print(x,y);x+y}))
//(5,1)(6,3)(9,5)(14,7)(21,9)30
println(list.foldLeft(5)((x:Int,y:Int)=>{print(x,y);x+y}))
3、groupBy
针对对偶的集合,可以按照一个元素进行分组,返回Map类型。
//groupBy
val array = List(("a",3),("a",333),("b",3),("b",333),("a","4"))
//Map(b -> List((b,3), (b,333)), a -> List((a,3), (a,333), (a,4)))
println(array.groupBy(_._1))
//Map(4 -> List((a,4)), 333 -> List((a,333), (b,333)), 3 -> List((a,3), (b,3)))
println(array.groupBy(_._2))
//多元数组先转为二元组
val e = List(("a",1000,2),("a",2222,3),("d",6888,333),("c",13,3),("c",14,4))
val f = e.map(r=>{(r._1,(r._2,r._3))})
println(f)
4、scan
扫描,即对某个集合的所有元素做fold操作,但是会把产生的所有中间结果放置于一个集合中保存。
//scan函数
val s1 = (1 to 5)
println(s1)
val s2 = s1.scanLeft(1)(_+_)
println("s2="+s2)//s2=Vector(1, 2, 4, 7, 11, 16)
val s3 = s1.scanLeft(10)(_-_)
println("s3="+s3)//s3=Vector(10, 9, 7, 4, 0, -5)
val s4 = s1.scanRight(1)(_+_)
println("s4="+s4)//s4=Vector(16, 15, 13, 10, 6, 1)
五、单词计数(练习)
/**单词计数
* 假设有单词数组:
* val arr = Array(“hello tom”,”hello jerry”,”hello hello”)
* 需要对Array中的每个单词进行统计计数
* @create 2019-11-12 19:16
*/
object Test8 {
def main(args: Array[String]): Unit = {
val array = Array("hello java","hello scala","hello hello")
val result=
array.flatMap(_.split("\\s")).map((_,1)).groupBy(_._1).map(t=>(t._1,t._2.size))
println(result)
}
}