Scala容器操作

Scala

必要的知识

函数的类型与类型推断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
object Test6 {
def main(args: Array[String]): Unit = {

}
//1.反思为什么可以这样写
val f : (Int,Double)=>Double =(x:Int,y:Double)=>x+y
//2.实际上发生了什么:省略了Function2,一共有22个
val f1 :Function2[Int,Double,Double]=(x:Int,y:Double)=>x+y
//3.进一步思考为什么能这样写:实际上(x:Int,y:Double)=>x+y 是调用了apply方法 new了一个特质,调用函数实际上是调用了apply方法
val f2 :Function2[Int,Double,Double]=new Function2[Int,Double,Double] {
override def apply(v1: Int, v2: Double): Double = v1+v2
}
//4.我们可以进一步的简化
val f4 =(x:Int,y:Double)=>x+y
//5.怎么表示元组
val tuple :Function2[Int,Double,Tuple2[Double,Int]]=new Function2[Int,Double,Tuple2[Double,Int]] {
override def apply(v1: Int, v2: Double): (Double, Int) = (v2,v1)
}
}

容器

数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
object Test1 {
def main(args: Array[String]): Unit = {
//定长数组的初始化
val ints = Array[Int](10)
println(ints.mkString(","))//10
val ints1 = new Array[Int](10)
println(ints1.mkString(","))//0,0,0,0,0,0,0,0,0,0
//使用()来访问数组的元素
//变长数组(缓冲数组)
val value = new ArrayBuffer[Int]()
//增操作1
//在末端添加
println(value.hashCode())
println(System.identityHashCode(value))
value += 1
//比较var val 地址值是否发生了变化
println(value.hashCode())
println(System.identityHashCode(value))
//增操作2
value += (2,3,4)
value ++= Array[Int](6)
value.appendAll( ArrayBuffer[Int](1,2,3))
println(value)
//删操作
value.remove(0)//索引
value.remove(0,2)//从索引0处删除2个元素
value.trimEnd(3)//删除后三个元素
//改操作
value(0) = 100
}
}
1
2
3
4
5
6
7
8
9
//二维数组
val array = Array.ofDim[Int](3, 4)
array(0)(0) =4
//遍历
for (index <- array){
for (i <- index){
println(i+"\t" )
}
}

列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//迭代器
object Test2 {
def main(args: Array[String]): Unit = {
//Trait Iterable
val value = List[String]("hbase", "hive", "mysql", "clickhouse", "kylin")
//xs.iterator返回一个迭代器
value.iterator.reduce(_+_).foreach(println)
//返回一个固定大小的迭代器
value grouped 2 foreach(println)
//返回一个固定大小的滑动窗口
value sliding 2 foreach(println)
//返回最后N元素
value.takeRight(2).foreach(println)
//返回除了最后N个元素的元素
value.dropRight(2).foreach(println)
//zip操作
val value1 = List[String]("mapreduce","spark","strom")
println(value.zip(value1))
//返回元组对应其索引的集合
println(value1.zipWithIndex)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//列表常用方法
object Test3 {
def main(args: Array[String]): Unit = {
//构建list
val list1 = "MapReduce" :: "spark" :: "strom" :: Nil
val list2 = "hive" :: list1 :: Nil
//(::: 左右两边都要为集合)
val list3 = "flink" :: list1 ::: Nil
println(list1) //List(MapReduce, spark, strom)
println(list2) //List(hive, List(MapReduce, spark, strom))
println(list3) //List(flink, MapReduce, spark, strom)
//list的底层是链表,是不可变的如下操作
val value = List[Int](1, 2, 3, 4, 5, 6, 7)
//1.判断是否为空
println(value.isEmpty)
//2.取值操作
println(value.head) //头一个
println(value.tail) //除了第一个外所有元素
println(value.init) //返回最后一个元素
println(value.last) //返回最后一个元素之外的其他元素
println(value.tail.head) //返回第二个元素
//使用下标访问,反转操作,返回所有下标
println(value(0))
println(value.reverse)
value.indices.foreach(println)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//列表
object Test4 {
def main(args: Array[String]): Unit = {
val value = List[Int](1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
println(value.take(3)) //获取前三个元素
println(value.drop(3)) //删除前三个元素
val tuple: (List[Int], List[Int]) = value splitAt 2 //从第N个拆分
println(tuple)
//扁平化操作
println(List(List(1, 2), List(3, 4), List(5, 6)).flatten)
//连接操作
val x1 = List(1, 2, 3)
val x2 = List("spark", "strom", "mapreduce")
println(x1.zip(x2).unzip)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//列表转换
object Test5 {
def main(args: Array[String]): Unit = {
val list = List(List("sprak", "strom"), List("mapreduce", "hive"))
//map操作,对list集合的每个元素的操作
val value: List[List[List[String]]] = list.map(data => data.map(data => data.split(",").toList))
value.foreach(println) //List(List(sprak), List(strom)) List(List(mapreduce), List(hive))
//flatten扁平化,扁平一次
val flatten: List[List[String]] = value.flatten
val flatten1: List[String] = flatten.flatten
println(flatten1) //List(sprak, strom, mapreduce, hive)
//flatmap,结合map和flatten的功能
val value1: List[String] = list.flatMap(data => data.flatMap(data => data.split(",").toList))
println(value1)//List(sprak, strom, mapreduce, hive)
//foreach,返回值类型为unit
val unit: Unit = list.foreach(data => println(data.toString().split(",").toList))
//List(List(sprak, strom)) List(List(mapreduce, hive))
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//列表过滤
object Test6 {
def main(args: Array[String]): Unit = {
val list = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
//filter用于过滤元素,返回满足条件的元素的新集合
println(list.filter(_ > 6))//List(7, 8, 9, 10)
//partition按照筛选条件对元素进行分组,返回类型的元组类型
println(list.partition(_ % 2 == 0))//(List(2, 4, 6, 8, 10),List(1, 3, 5, 7, 9))
//find,查找第一个满足条件的值,可能不存在,使用getorelse来避免空指针
val finddata: Option[Int] = list.find(_ > 9)
val i = finddata.getOrElse(9)
println(i)//10
//takewhile,按照筛选条件遍历直到第一个不满足的值,返回已经遍历过的值
val value: List[Int] = list.takeWhile(_ < 6)
println(value)//List(1, 2, 3, 4, 5)
//dropwhile,按照筛选条件,直到遍历到第一个不满足条件的元素,返回尚未遍历过的元素
println(list.dropWhile(_ < 6))//List(6, 7, 8, 9, 10)
//span,结合了takewhile和dropwhile,把满足和不满足的值分别放到不同的元组中
val tuple: (List[Int], List[Int]) = list.span(_ < 6)
println(tuple)//(List(1, 2, 3, 4, 5),List(6, 7, 8, 9, 10))
}
}

映射

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
object Test7 {
def main(args: Array[String]): Unit = {
//构建map
val map1 = Map[String, Int]()
val map2 = Map[String, Int]("1" -> 1, "2" -> 2, "3" -> 3)
val map3 = Map[Seq[String], List[String]]((Seq("小明"), List("中华")), (null, null))
//获取值
println(map2("1"))
println(map1.getOrElse("1", "1"))
//增删改,不可变映射不能增加元素
val map4 = mutable.Map[Int, Int]()
//存在则是修改,不存在则是增添
println(System.identityHashCode()) //1007251739
println(map4.hashCode()) //-1609326920
map4(1) = 1
map4 += (2 -> 2, 3 -> 3)
println(map4) //HashMap(1 -> 1, 2 -> 2, 3 -> 3)
println(System.identityHashCode()) //1007251739
println(map4.hashCode()) //-151370400
//首先理解immutable和mutable,前者为不可变,后者为可变。
// 这里面的可变性指的是在原List上是否可变,但是如果我改变了该List值,赋值给另外一个List,那是可以的。
//接下来理解val,var,前者为不可变,后者为可变,
// 这个指的的后面List的指向,val指向的地址值不可变,var指向的地址值可变。
}
}

案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//如何用reduceLeft得到数组中的最大元素?
object Test1 {
def main(args: Array[String]): Unit = {
var array = Array[Int](1, 5, 7, 8, 9, 12, 67, 45, 7889)
println(array.reduceLeft(rmax))
}
//使用泛型增加复用性
def rmax[S, T](num: S, num2: T) = {
if (num.toString.toInt.isInstanceOf[Int] && num2.toString.toInt.isInstanceOf[Int]) {
if (num.toString.toInt < num2.toString.toInt) num2 else num
}
else throw new Exception
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//抽象控制的简单案例-实现if
object Test2 {
def main(args: Array[String]): Unit = {
var number = 10
myif(number > 4){
number-= 1
println(number)
}
}
def myif(f: => Boolean)(f1: => Unit):Unit={
if(f){
f1
myif(f)(f1)
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//Wordcount案例(foldLeft方法)
object Test3 {
def main(args: Array[String]): Unit = {
var words = "AAAABDDDDBBBWWWJJCCCCJTTEEE"
//使用reducefold方法,分别使用不可变,可变集合
val value = words.foldLeft(mutable.Map[Char, Int]())(myreducefold)
val value1 = words.foldLeft(Map[Char, Int]())(myReducefold)
println(value)
println(value1)
// println(mumap)
//HashMap(A -> 4, B -> 4, C -> 4, D -> 4, T -> 2, E -> 3, W -> 3, J -> 3)
//HashMap(E -> 3, T -> 2, J -> 3, A -> 4, B -> 4, C -> 4, W -> 3, D -> 4)
//HashMap()
}

//方法一
def myreducefold(map: mutable.Map[Char, Int], char: Char) = {
map.get(char) match {
case Some(value) => map + (char -> (value.toInt + 1))
case None => map + (char -> 1)
}
}

//方法二
def myReducefold(map: Map[Char, Int], char: Char) = {
map + (char -> (map.getOrElse(char, 0) + 1))
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//使用Scala实现一个方法,使得返回数组中,分别等于num,大于num,小于num的元素的个数,getNum(Array(1,2,3,4,5,6),2)结果为(1,1,4)
object Test4 {
def main(args: Array[String]): Unit = {
val array = Array[Int](1, 2, 3, 4, 5, 6)
//考虑模式匹配
array.groupBy {
case x if x < 2 => "<2"
case y if y == 2 => "=2"
case z if z > 2 => ">2"
}.map(data => (data._1, data._2.size)).foreach(println)

//考虑foldleft
val a = 0
val b = 0
val c = 0
array.foldLeft(a, b, c)((x, y) => {
(if (y < 2) {
(x._1 + 1)
} else x._1,
if (y == 2) {
(x._2 + 1)
} else x._2,
if (y > 2) {
(x._3 + 1)
} else x._3)
})
//考虑aggregate聚合方法
var result = array.aggregate(a, b, c)((x, y) => {
(if (y > 2) {
x._1 + 1
} else x._1,
if (y == 2) {
x._2 + 1
} else x._2,
if (y < 2) {
x._3 + 1
} else x._3)
}, null)
println((result._1, result._2, result._3))

//考虑过滤
println((array.count(_ > 2), array.count(_ < 2), array.count(_ == 2)))
}
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//偏函数实现过滤功能
object Test5 {
def main(args: Array[String]): Unit = {
var array = Array(1, 2, 3, 4, 5, "scala")
val ints: Array[Int] = array.collect({
case x: Int if (x % 2 == 1) => x
})
println(ints.mkString(","))

val ints1: Array[Int] = array.collect(myfilter)
println(ints1.mkString(","))
}

val myfilter: PartialFunction[Any, Int] = {
case d: Int if (d % 2 == 0) => d
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//统计字符串中的不同字母出现的位置并排序
object Test6 {
def main(args: Array[String]): Unit = {
var st: String = "AANNCCCRRUUSSRT"
var map = mutable.Map[Char, ListBuffer[Int]]()
var index: Int = 0
st.foreach(data => {
map.get(data) match {
//case有值和null
//往集合中添加索引
case Some(value) => map(data) = value :+ index
case None => map += (data -> ListBuffer[Int] (
index)
)
}
index += 1
}
)
val value: Seq[(Char, ListBuffer[Int])] = map.toList.sortBy(_._1).reverse
println(value)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//unapplySeq提取器用法
object Test7 {
def main(args: Array[String]): Unit = {
var st = "小明,小华,小聚,小米"
val tuple: (String, String) = st match {
case Name(a, b, c, d) => (c, d)
}
println(tuple)
}
}

object Name {
def unapplySeq(arg: String): Option[Array[String]] = {
if (arg.length == 0) None else Some(arg.split(","))
}
}