个人随笔
目录
Scala学习之路 (四)Scala的数组、映射、元组、集合
2019-12-10 23:29:12

转自:https://www.cnblogs.com/qingyunzong/p/8858465.html

一、数组

1、定长数组和边长数组

  1. import scala.collection.mutable.ArrayBuffer
  2. object TestScala {
  3. def main(args: Array[String]) {
  4. //初始化一个长度为8的定长数组,其所有元素均为0
  5. val arr1 = new Array[Int](8)
  6. //直接打印定长数组,内容为数组的hashcode值
  7. println("arr1="+arr1)
  8. //将数组转换成数组缓冲,就可以看到原数组中的内容了
  9. //toBuffer会将数组转换长数组缓冲
  10. println("arr1.toBuffer="+arr1.toBuffer)
  11. //注意:如果new,相当于调用了数组的apply方法,直接为数组赋值
  12. //初始化一个长度为1的定长数组
  13. val arr2 = Array[Int](10)
  14. println("arr2.toBuffer="+arr2.toBuffer)
  15. //定义一个长度为3的定长数组
  16. val arr3 = Array("hadoop", "storm", "spark")
  17. //使用()来访问元素
  18. println("arr3(2)="+arr3(2))
  19. //////////////////////////////////////////////////
  20. //变长数组(数组缓冲)
  21. //如果想使用数组缓冲,需要导入import scala.collection.mutable.ArrayBuffer包
  22. var ab = ArrayBuffer[Int]()
  23. //向数组缓冲的尾部追加一个元素
  24. //+=尾部追加元素
  25. ab += 1
  26. //追加多个元素
  27. ab += (2, 3, 4, 5)
  28. //追加一个数组++=
  29. ab ++= Array(6, 7)
  30. //追加一个数组缓冲
  31. ab ++= ArrayBuffer(8,9)
  32. //打印数组缓冲ab
  33. //在数组某个位置插入元素用insert
  34. ab.insert(0, -1, 0)
  35. //删除数组某个位置的元素用remove
  36. ab.remove(8, 2)
  37. println("ab="+ab)
  38. }
  39. }

运行结果

  1. arr1=[I@47fd17e3
  2. arr1.toBuffer=ArrayBuffer(0, 0, 0, 0, 0, 0, 0, 0)
  3. arr2.toBuffer=ArrayBuffer(10)
  4. arr3(2)=spark
  5. ab=ArrayBuffer(-1, 0, 1, 2, 3, 4, 5, 6, 9)

2、遍历数组

(1)增强for循环
(2)好用的until会生成脚标,0 until 10 包含0不包含10

  1. def main(args: Array[String]) {
  2. //初始化一个数组
  3. val arr = Array(1,2,3,4,5,6,7,8)
  4. //增强for循环
  5. for(i <- arr)
  6. print(i+"\t")
  7. println()
  8. //好用的until会生成一个Range
  9. //reverse是将前面生成的Range反转
  10. for(i <- (0 until arr.length).reverse)
  11. print(arr(i))
  12. }

运行结果

  1. 1 2 3 4 5 6 7 8
  2. 87654321

3、数组转换

yield关键字将原始的数组进行转换会产生一个新的数组,原始的数组不变

  1. ef main(args: Array[String]) {
  2. //定义一个数组
  3. val arr = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)
  4. //将偶数取出乘以10后再生成一个新的数组
  5. val res = for (e <- arr if e % 2 == 0) yield e * 10
  6. println(res.toBuffer)
  7. //更高级的写法,用着更爽
  8. //filter是过滤,接收一个返回值为boolean的函数
  9. //map相当于将数组中的每一个元素取出来,应用传进去的函数
  10. val r = arr.filter(_ % 2 == 0).map(_ * 10)
  11. println(r.toBuffer)
  12. }

运行结果

  1. ArrayBuffer(20, 40, 60, 80)
  2. ArrayBuffer(20, 40, 60, 80)

4、常用数组的算法

  1. def main(args: Array[String]): Unit = {
  2. //定义一个数组
  3. val arr = Array(1, 4, 3, 2, 5, 6, 7, 8, 9)
  4. //sum求和
  5. println(arr.sum)
  6. //max求最大值
  7. println(arr.max)
  8. //sorted排序
  9. println(arr.sorted.toBuffer)
  10. }

运行结果

  1. 45
  2. 9
  3. ArrayBuffer(1, 2, 3, 4, 5, 6, 7, 8, 9)

二、映射(Map)

在Scala中,把哈希表这种数据结构叫做映射

1、构建映射

2、获取映射中的值

getOrElse:有就返回对应的值,没有就返回默认值

注意:在Scala中,有两种Map,一个是immutable包下的Map,该Map中的内容不可变;另一个是mutable包下的Map,该Map中的内容可变 (val var)

注意:通常我们在创建一个集合是会用val这个关键字修饰一个变量(相当于java中的final),那么就意味着该变量的引用不可变,该引用中的内容是不是可变,取决于这个引用指向的集合的类型

是否可以修改值

Mutable 可以修改map里面的值
Immutable 不可以修改里面的值

是否可以追加元素

mutable var/val 都可以追加元素
imtable var 可以追加,val不可以追加


三、元组

映射是K/V对偶的集合,对偶是元组的最简单形式,元组可以装着多个不同类型的值。

1、创建元组

2、获取元组中的值

3、将对偶的元组转换成映射

4、拉链操作

zip命令可以将多个值绑定在一起

注意:如果两个数组的元素个数不一致,拉链操作后生成的数组的长度为较小的那个数组的元素个数


四、集合

Scala 集合类系统地区分了可变的和不可变的集合。可变集合可以在适当的地方被更新或扩展。这意味着你可以修改,添加,移除一个集合的元素。而不可变集合类,相比之下,永远不会改变。不过,你仍然可以模拟添加,移除或更新操作。但是这些操作将在每一种情况下都返回一个新的集合,同时使原来的集合不发生改变

所有的集合类都可以在包scala.collection 或scala.collection.mutable,scala.collection.immutable,scala.collection.generic中找到。客户端代码需要的大部分集合类都独立地存在于3种变体中,它们位于scala.collection, scala.collection.immutable, scala.collection.mutable包。每一种变体在可变性方面都有不同的特征。


scala.collection.immutable:包是的集合类确保不被任何对象改变。例如一个集合创建之后将不会改变。因此,你可以相信一个事实,在不同的点访问同一个集合的值,你将总是得到相同的元素。

scala.collection.mutable:包的集合类则有一些操作可以修改集合。所以处理可变集合意味着你需要去理解哪些代码的修改会导致集合同时改变。

scala.collection:包中的集合,既可以是可变的,也可以是不可变的。例如:collection.IndexedSeq[T]] 就是 collection.immutable.IndexedSeq[T] 和collection.mutable.IndexedSeq[T]这两类的超类。scala.collection包中的根集合类中定义了相同的接口作为不可变集合类,同时,scala.collection.mutable包中的可变集合类代表性的添加了一些有辅助作用的修改操作到这个immutable 接口。


根集合类与不可变集合类之间的区别是不可变集合类的客户端可以确保没有人可以修改集合。然而,根集合类的客户端仅保证不修改集合本身。即使这个集合类没有提供修改集合的静态操作,它仍然可能在运行时作为可变集合被其它客户端所修改。

默认情况下,Scala 一直采用不可变集合类。例如,如果你仅写了Set 而没有任何加前缀也没有从其它地方导入Set,你会得到一个不可变的set,另外如果你写迭代,你也会得到一个不可变的迭代集合类,这是由于这些类在从scala中导入的时候都是默认绑定的。为了得到可变的默认版本,你需要显式的声明collection.mutable.Set或collection.mutable.Iterable.

一个有用的约定,如果你想要同时使用可变和不可变集合类,只导入collection.mutable包即可。

  1. import scala.collection.mutable //导入包scala.collection.mutable

然而,像没有前缀的Set这样的关键字, 仍然指的是一个不可变集合,然而mutable.Set指的是可变的副本(可变集合)。

集合树的最后一个包是collection.generic。这个包包含了集合的构建块。集合类延迟了collection.generic类中的部分操作实现,另一方面集合框架的用户需要引用collection.generic中类在异常情况中。

为了方便和向后兼容性,一些导入类型在包scala中有别名,所以你能通过简单的名字使用它们而不需要import。这有一个例子是List 类型,它可以用以下两种方法使用,如下:

  1. scala.collection.immutable.List // 这是它的定义位置
  2. scala.List //通过scala 包中的别名
  3. List // 因为scala._ // 总是是被自动导入。

下面的图表显示了scala.collection包中所有的集合类。这些都是高级抽象类或特性,它们通常具备和不可变实现一样的可变实现。

下面的图表显示scala.collection.immutable中的所有集合类。

下面的图表显示scala.collection.mutable中的所有集合类。

1、List

不可变的序列 import scala.collection.immutable._

在Scala中列表要么为空(Nil表示空列表)要么是一个head元素加上一个tail列表。

9 :: List(5, 2) :: 操作符是将给定的头和尾创建一个新的列表

注意::: 操作符是右结合的,如9 :: 5 :: 2 :: Nil相当于 9 :: (5 :: (2 :: Nil))

  1. def main(args: Array[String]): Unit = {
  2. //创建一个不可变集合
  3. val list1 = List(1,2,3)
  4. //将0插入到集合list1的前面生成一个新的list
  5. val list2 = 0 :: list1
  6. val list3 = list1.:: (0)
  7. val list4 = 0 +: list1
  8. val list5 = list1. +: (0)
  9. println("list2=" + list2)
  10. println("list3=" + list3)
  11. println("list4=" + list4)
  12. println("list5=" + list5)
  13. //将3插入到集合list1的后面生成一个新的list
  14. val list6 = list1 :+ 3
  15. println("list6="+list6)
  16. //将2个list集合合并成一个新的list集合
  17. val list0 = List(7,8,9)
  18. println("list0="+list0)
  19. val list7 = list1 ++ list0
  20. println("list7="+list7)
  21. //将list0插入到list1前面生成一个新的集合
  22. val list8 = list0 ++: list1
  23. println("list8="+list8)
  24. //将list1插入到list0前面生成一个新的集合
  25. val list9 = list1 ++: list0
  26. println("list9="+list9)
  27. }

运行结果

  1. list2=List(0, 1, 2, 3)
  2. list3=List(0, 1, 2, 3)
  3. list4=List(0, 1, 2, 3)
  4. list5=List(0, 1, 2, 3)
  5. list6=List(1, 2, 3, 3)
  6. list0=List(7, 8, 9)
  7. list7=List(1, 2, 3, 7, 8, 9)
  8. list8=List(7, 8, 9, 1, 2, 3)
  9. list9=List(1, 2, 3, 7, 8, 9)
可变的序列 import scala.collection.mutable._
  1. def main(args: Array[String]): Unit = {
  2. //构建一个可变序列
  3. val list1 = ListBuffer[Int](1,2,3)
  4. //创建一个空的可变序列
  5. val list2 = new ListBuffer[Int]
  6. //向list2中追加元素,注意:没有生成新的集合
  7. list2 += 6
  8. list2.append(7)
  9. println("list2=" + list2)
  10. //将list2中的元素追加到list1中,注意:没有生成新的集合
  11. list1 ++= list2
  12. print("list1=" + list1)
  13. //将list1和list2合并成一个新的list集合,注意:生成新的集合
  14. val list3 = list1 ++ list2
  15. println("list3=" + list3)
  16. //将元素追加到list1后面生成一个新的集合
  17. val list4 = list1 :+ 9
  18. print("list4=" + list4)
  19. }

运行结果

  1. list2=ListBuffer(6, 7)
  2. list1=ListBuffer(1, 2, 3, 6, 7)list3=ListBuffer(1, 2, 3, 6, 7, 6, 7)
  3. list4=ListBuffer(1, 2, 3, 6, 7, 9)

2、Set

不可变的Set
  1. def main(args: Array[String]): Unit = {
  2. //创建一个空的set
  3. val set1 = new HashSet[Int]()
  4. println("set1=" + set1)
  5. //将元素和set合并生成一个新的set,原有set不变
  6. val set2 = set1 + 4
  7. println("set2=" + set2)
  8. //set中元素不能重复
  9. val set3 = set1 ++ Set(5,6,7)
  10. println("set3=" + set3)
  11. val set4 = Set(4,3,2) ++ set2
  12. println("set4=" + set4)
  13. }

运行结果

  1. set1=Set()
  2. set2=Set(4)
  3. set3=Set(5, 6, 7)
  4. set4=Set(4, 3, 2)

注意:不要引入Java的HashSet,建议直接Set(1,2,3)

可变的Set
  1. def main(args: Array[String]): Unit = {
  2. //创建一个可变的set
  3. val set1 = new mutable.HashSet[Int]()
  4. println("list1=" + set1)
  5. //向set1中添加元素
  6. set1 += 4
  7. //add等价于+=
  8. set1.add(5)
  9. set1 ++= Set(6,7,8)
  10. println("set1="+set1)
  11. //删除一个元素
  12. set1 -= 8
  13. set1.remove(7)
  14. println("set1=" + set1)
  15. }

运行结果

  1. list1=Set()
  2. set1=Set(5, 6, 7, 4, 8)
  3. set1=Set(5, 6, 4)
 367

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号-2