Scala集合类型详解

Scala集合

Scala提供了一套很好的集合实现,提供了一些集合类型的抽象。

Scala 集合分为可变的和不可变的集合。

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

 

集合中基本结构:

 

 

 

几种常用集合类型示例

 

[java]  view plain  copy
  1. // 定义整型 List  
  2. val x = List(1234)  
  3.   
  4. // 定义 Set  
  5. var x = Set(1357)  
  6.   
  7. // 定义 Map  
  8. val x = Map("one" -> 1"two" -> 2"three" -> 3)  
  9.   
  10. // 创建两个不同类型元素的元组  
  11. val x = (10"Runoob")  
  12.   
  13. // 定义 Option  
  14. val x: Option[Int] = Some(5)  



Scala List(列表)

Scala 列表类似于数组,它们所有元素的类型都相同,但是它们也有所不同:列表是不可变的,值一旦被定义了就不能改变,其次列表 具有递归的结构(也就是链接表结构)而数组不是。

列表的元素类型 T 可以写成 List[T]。例如,以下列出了多种类型的列表:

 

[java]  view plain  copy
  1. // 字符串列表  
  2. val site: List[String] = List("Sina""Google""Baidu")  
  3.   
  4. // 整型列表  
  5. val nums: List[Int] = List(1234)  
  6.   
  7. // 空列表  
  8. val empty: List[Nothing] = List()  
  9.   
  10. // 二维列表  
  11. val dim: List[List[Int]] =  
  12.   List(  
  13.     List(100),  
  14.     List(010),  
  15.     List(001)  
  16.   )  


构造列表的两个基本单位是 Nil 和 ::

Nil 也可以表示为一个空列表。

以上实例我们可以写成如下所示:::)符号连接顺序是从右到左

[java]  view plain  copy
  1. // 字符串列表  
  2. val site = "Sina" :: ("Google" :: ("Baidu" :: Nil))  
  3.   
  4. // 整型列表  
  5. val nums = 1 :: (2 :: (3 :: (4 :: Nil)))  
  6.   
  7. // 空列表  
  8. val empty = Nil  
  9.   
  10. // 二维列表  
  11. val dim = (1 :: (0 :: (0 :: Nil))) ::  
  12.   (0 :: (1 :: (0 :: Nil))) ::  
  13.   (0 :: (0 :: (1 :: Nil))) :: Nil  


基本操作

Scala列表有三个基本操作:

  1. head 返回列表第一个元素
  2. tail 返回一个列表,包含除了第一元素之外的其他元素:(是一个列表或者Nil)
  3. isEmpty 在列表为空时返回true

 

对于Scala列表的任何操作都可以使用这三个基本操作来表达。代码示例如下:

[java]  view plain  copy
  1. val site = "Sina" :: ("Google" :: ("Baidu" :: Nil))  
  2. val nums = Nil  
  3. //打印测试head、tail、isEmpty功能  
  4. println(site.head)  
  5. println(site.tail)  
  6. println(site.isEmpty)  
  7. println(nums.isEmpty)  

打印结果为:

[java]  view plain  copy
  1. Sina  
  2. List(Google, Baidu)  
  3. false  
  4. true  

连接列表

你可以使用  :::  、 List.:::()  或  List.concat()  方法来连接两个或多个列表。

代码示例如下:

[java]  view plain  copy
  1. val site1 = "Sina" :: ("Google" :: ("Baidu" :: Nil))  
  2. val site2 = "Facebook" :: ("Taobao" :: Nil)  
  3.   
  4. // 使用 ::: 运算符  
  5. var combine = site1 ::: site2  
  6. println( "site1 ::: site2 : " + combine )  
  7.   
  8. // 使用 list.:::() 方法,注意:结果为site2列表元素在前,site1在后  
  9. combine = site1.:::(site2)  
  10. println( "site1.:::(site2) : " + combine )  
  11.   
  12. // 使用 concat 方法  
  13. combine = List.concat(site1, site2)  
  14. println( "List.concat(site1, site2) : " + combine  )  

打印结果:

[java]  view plain  copy
  1. site1 ::: site2 : List(Sina, Google, Baidu, Facebook, Taobao)  
  2. site1.:::(site2) : List(Facebook, Taobao, Sina, Google, Baidu)  
  3. List.concat(site1, site2) : List(Sina, Google, Baidu, Facebook, Taobao)  

 

List.fill()

我们可以使用 List.fill() 方法来创建一个指定重复数量的元素列表:

[java]  view plain  copy
  1. val site = List.fill(3)("Baidu"// 重复 Runoob 3次  
  2. println( "site : " + site  )  
  3.   
  4. val num = List.fill(10)(2)         // 重复元素 2, 10 次  
  5. println( "num : " + num  )  

打印结果为:

[java]  view plain  copy
  1. site : List(Baidu, Baidu, Baidu)  
  2. num : List(2222222222)  


List.tabulate()

List.tabulate() 方法是通过给定的函数来创建列表。

方法的第一个参数为元素的数量,可以是二维的,第二个参数为指定的函数,我们通过指定的函数计算结果并返回值插入到列表中,起始值为 0,实例如下:

[java]  view plain  copy
  1. // 通过给定的函数创建 5 个元素  
  2. val squares = List.tabulate(6)(n => n * n)  
  3. println( "一维 : " + squares  )  
  4.   
  5. // 创建二维列表  
  6. val mul = List.tabulate( 4,5 )( _ * _ )  
  7. println( "二维 : " + mul  )  


打印结果为:

[java]  view plain  copy
  1. 一维 : List(01491625)  
  2. 二维 : List(List(00000), List(01234), List(02468), List(036912))  


List.reverse

List.reverse 用于将列表的顺序反转,实例如下:

[java]  view plain  copy
  1. val site = "Sina" :: ("Google" :: ("Baidu" :: Nil))  
  2. println( "反转前 : " + site )  
  3. println( "反转前 : " + site.reverse )  


打印结果为:

[java]  view plain  copy
  1. 反转前 : List(Sina, Google, Baidu)  
  2. 反转前 : List(Baidu, Google, Sina)  


列表缓存(ListBuffer)

List类能够提供对列表头部,而非尾部的快速访问。如果需要向结尾添加对象,则需要先对表头前缀元素方式反向构造列表,完成之后再调用reverse。

上述问题另一种解决方式就是使用ListBuffer,这可以避免reverse操作。ListBuffer是可变对象,它可以更高效的通过添加元素来构建列表。

使用ListBuffer替代List另一个理由是避免栈溢出风险。

 

ListBuffer使用示例:

[java]  view plain  copy
  1. val buf: ListBuffer[Int] = new ListBuffer[Int]  
  2. //往后添加  
  3. buf += 1  
  4. buf += 2  
  5.   
  6. //前缀添加  
  7. val buf2 = 3 +: buf  
  8. println(buf2.toString())  
  9.   
  10. //ListBuffer转List  
  11. println(buf2.toList.toString())  


List常用方法

  • 参考底部附录:

 

 

 

Scala队列和栈

队列

如果你需要先进先出序列,你可以使用Queue(队列)。Scala集合提供了可变和不可变的Queue。

 

不可变Queue代码示例:

[java]  view plain  copy
  1. //使用伴生对象创建一个queue  
  2. val que = Queue[Int]()  
  3.   
  4. //使用enqueue为不可变队列添加元素  
  5. val que1 = que.enqueue(1)  
  6.   
  7. //往队列添加多个元素,把集合作为enqueue的参数  
  8. val que2 = que1.enqueue(List(2,3,4,5))  
  9.   
  10. //从队列头部移除元素,使用dequeue  
  11. //第一个参数为头部移除的元素,第二个参数为剩下的队列  
  12. val (elem1,que3) = que2.dequeue  
  13.   
  14. //打印移除的元素  
  15. println(elem1)  
  16.   
  17. //打印剩下的队列  
  18. println(que3)  

 

打印结果为:

[java]  view plain  copy
  1. 1  
  2. Queue(2345)  


可变Queue代码示例:


[java]  view plain  copy
  1. //使用伴生对象创建一个可变queue  
  2. var que = scala.collection.mutable.Queue[String]()  
  3.   
  4. //使用 += 符号添加单个元素  
  5. que += "A"  
  6.   
  7. //使用 ++= 符号添加多个元素  
  8. que ++= List("B","C","D")  
  9.   
  10. //使用dequeue移除头部元素  
  11. val a = que.dequeue  
  12.   
  13. //打印移除的元素  
  14. println(a)  
  15.   
  16. //打印队列中剩下的元素  
  17. print(que)  

打印结果:

[java]  view plain  copy
  1. A  
  2. Queue(B, C, D)  

 

如果需要的是后进先出,你可以使用Stack,它同样在Scala的集合中有可变和不可变版本。元素的推入使用push,弹出用pop,只获取栈顶元素而不移除可以使用top。

 

可变栈示例:

[java]  view plain  copy
  1. //使用Stack类的伴生对象创建Stack对象  
  2. var stack = scala.collection.mutable.Stack[Int]()  
  3.   
  4. //往栈stack中压如元素  
  5. stack.push(1)  
  6. stack.push(2)  
  7. stack.push(3)  
  8.   
  9. //打印查看栈内元素  
  10. println(stack)  
  11.   
  12. //获取栈顶元素的值  
  13. val tval = stack.top  
  14. println("栈顶元素为 : " + tval)  
  15.   
  16. //移除栈顶元素  
  17. val pval = stack.pop()  
  18. println("移除的栈顶元素为 : " + pval)  
  19.   
  20. //打印移除栈顶元素后,剩下的栈内元素  
  21. println(stack)  

打印结果:

[java]  view plain  copy
  1. Stack(321)  
  2. 栈顶元素为 : 3  
  3. 移除的栈顶元素为 : 3  
  4. Stack(21)  


队列和栈常用操作

  • 参考底部附录:

 

 

 

Scala Set(集)

  1. Scala Set(集)是没有重复的对象集合,所有的元素都是唯一的。
  2. Scala 集合分为可变的和不可变的集合。
  3. 默认情况下,Scala 使用的是不可变集合,如果想使用可变集合,需引用 scala.collection.mutable.Set 包。
  4. 默认引用 scala.collection.immutable.Set。

 

不可变集合实例如下:

[java]  view plain  copy
  1. val set = Set(1,2,3)  
  2. println(set.getClass.getName) //  
  3.   
  4. println(set.exists(_ % 2 == 0)) //true  
  5. println(set.drop(1)) //Set(2,3)  

打印结果为:

[java]  view plain  copy
  1. scala.collection.immutable.Set$Set3  
  2. true  
  3. Set(23)  


如果需要使用可变集合需要引入 scala.collection.mutable.Set:

[java]  view plain  copy
  1. import scala.collection.mutable.Set // 可以在任何地方引入 可变集合  
  2.   
  3. val mutableSet = Set(1,2,3)  
  4. println(mutableSet.getClass.getName) // scala.collection.mutable.HashSet  
  5. //往集合内添加元素4  
  6. mutableSet.add(4)  
  7. //删除值为1的元素  
  8. mutableSet.remove(1)  
  9. //添加元素5  
  10. mutableSet += 5  
  11. //删除值为3的元素  
  12. mutableSet -= 3  
  13.   
  14. println(mutableSet) // Set(5, 3, 4)  
  15.   
  16. val another = mutableSet.toSet  
  17. println(another.getClass.getName) // scala.collection.immutable.Set  

注意: 虽然可变Set和不可变Set都有添加或删除元素的操作,但是有一个非常大的差别。对不可变Set进行操作,会产生一个新的set,原来的set并没有改变,这与List一样。 而对可变Set进行操作,改变的是该Set本身,与ListBuffer类似。

 

Set集合基本操作

Scala Set集合有三个基本操作:

  1. head 返回集合第一个元素
  2. tail 返回一个集合,包含除了第一元素之外的其他元素
  3. isEmpty 在集合为空时返回true

对于Scala集合的任何操作都可以使用这三个基本操作来表达。

代码示例如下:


[java]  view plain  copy
  1. val site = Set("Sina""Google""Baidu")  
  2. val nums: Set[Int] = Set()  
  3.   
  4. println( "head : " + site.head )  
  5. println( "tail : " + site.tail )  
  6. println( "isEmpty : " + site.isEmpty )  
  7. println( "isEmpty : " + nums.isEmpty )  


打印结果为:

[java]  view plain  copy
  1. head : Sina  
  2. tail : Set(Google, Baidu)  
  3. isEmpty : false  
  4. isEmpty : true  


连接集合

你可以使用 ++ 运算符或 Set.++() 方法来连接两个集合。如果元素有重复的就会移除重复的元素。实例如下:

[java]  view plain  copy
  1. val site1 = Set("Sina""Google""Baidu")  
  2. val site2 = Set("Faceboook""Taobao")  
  3.   
  4. // ++ 作为运算符使用  
  5. var site = site1 ++ site2  
  6. println( "site1 ++ site2 : " + site )  
  7.   
  8. //  ++ 作为方法使用  
  9. site = site1.++(site2)  
  10. println( "site1.++(site2) : " + site )  

打印结果为:

[java]  view plain  copy
  1. site1 ++ site2 : Set(Faceboook, Taobao, Sina, Google, Baidu)  
  2. site1.++(site2) : Set(Faceboook, Taobao, Sina, Google, Baidu)  


 

查找集合中最大与最小元素

你可以使用 Set.min 方法来查找集合中的最小元素,使用 Set.max 方法查找集合中的最大元素。实例如下:

[java]  view plain  copy
  1. val num = Set(5,6,9,20,30,45)  
  2.   
  3. // 查找集合中最大与最小元素  
  4. println( "Set(5,6,9,20,30,45)  最小元素是 : " + num.min )  
  5. println( "Set(5,6,9,20,30,45)  最大元素是 : " + num.max )  

打印结果为:

[java]  view plain  copy
  1. Set(5,6,9,20,30,45)  最小元素是 : 5  
  2. Set(5,6,9,20,30,45)  最大元素是 : 45  


交集

你可以使用 Set.& 方法或 Set.intersect 方法来查看两个集合的交集元素。实例如下:

 

[java]  view plain  copy
  1. val num1 = Set(5,6,9,20,30,45)  
  2. val num2 = Set(50,60,9,20,35,55)  
  3.   
  4. // 交集  
  5. println( "num1.&(num2) : " + num1.&(num2) )  
  6. println( "num1.intersect(num2) : " + num1.intersect(num2) )  

 

打印结果为:

[java]  view plain  copy
  1. num1.&(num2) : Set(209)  
  2. num1.intersect(num2) : Set(209)  

Scala Set 常用方法

  • 参考底部附录:

 

 

 

Scala Map(映射)

  1. Map(映射)是一种可迭代的键值对(key/value)结构。
  2. 所有的值都可以通过键来获取。
  3. Map 中的键都是唯一的。
  4. Map 也叫哈希表(Hash tables)。
  5. Map 有两种类型,可变与不可变,区别在于可变对象可以修改它,而不可变对象不可以。
  6. 默认情况下 Scala 使用不可变 Map。如果你需要使用可变集合,你需要显式的引入 import scala.collection.mutable.Map 类
  7. 在 Scala 中 你可以同时使用可变与不可变 Map,不可变的直接使用 Map,可变的使用 mutable.Map。

 

以下实例演示了不可变 Map 的应用:

[java]  view plain  copy
  1. // 空哈希表,键为字符串,值为整型  
  2. var A:Map[Char,Int] = Map()  
  3.   
  4. // Map 键值对演示  
  5. val lang= Map("Java" -> "Oracle""C#" -> "Microsoft")  
  6. 或者  
  7. val lang= Map(("Java","Oracle"), ("C#" , "Microsoft"))  


定义 Map 时,需要为键值对定义类型。如果需要添加 key-value 对,可以使用 + 号,如下所示:


[java]  view plain  copy
  1. A += ('t' ->10 )  


 

Map 基本操作

Scala Map 几种基本操作:keys、values、isEmpty、赋值(可变映射)

代码示例:

Keys:

[java]  view plain  copy
  1. val lang = Map("Java" -> "Oracle",  
  2.   "C#" -> "Microsoft",  
  3.   "Swift" -> "Apple")  
  4. Values:  
  5. val nums: Map[Int, Int] = Map()  
  6. println( "lang 中的键为 : " + lang.keys )  
  7. println( "lang 中的值为 : " + lang.values )  

isEmpty:

[java]  view plain  copy
  1. println( "lang 是否为空 : " + lang.isEmpty )  
  2. println( "nums 是否为空 : " + nums.isEmpty )  

keys和isEmpty的打印结果为:

[java]  view plain  copy
  1. lang 中的键为 : Set(Java, C#, Swift)  
  2. lang 中的值为 : MapLike(Oracle, Microsoft, Apple)  
  3. lang 是否为空 : false  
  4. nums 是否为空 : true  


赋值:

[java]  view plain  copy
  1. var lang= scala.collection.mutable.Map("Java" -> "Oracle""C#" -> "Microsoft")  
  2. lang("Java") = "sun"  
  3. println(lang)  

打印结果为:

[java]  view plain  copy
  1. Map(C# -> Microsoft, Java -> sun)  


 

Map 合并

你可以使用 ++ 运算符或 Map.++() 方法来连接两个 Map,Map 合并时会移除重复的 key。以下演示了两个 Map 合并的实例:

 

[java]  view plain  copy
  1. val lang =Map("Java" -> "Oracle",  
  2.   "C#" -> "Microsoft",  
  3.   "Swift" -> "Apple")  
  4. val color = Map("blue" -> "#0033FF",  
  5.   "yellow" -> "#FFFF00",  
  6.   "red" -> "#FF0000")  
  7.   
  8. //  ++ 作为运算符  
  9. var colors = lang ++ color  
  10. println( "lang ++ colors : " + colors )  
  11.   
  12. //  ++ 作为方法  
  13. colors = lang.++(colors)  
  14. println( "lang.++(colors)) : " + colors )  


打印结果为:

[java]  view plain  copy
  1. lang ++ colors : Map(blue -> #0033FF, C# -> Microsoft, yellow -> #FFFF00, Java -> Oracle, red -> #FF0000, Swift -> Apple)  
  2. )  
  3.   
  4. //  ++ 作为运算符  
  5. var colors = lang ++ color  
  6. println( "lang ++ colors : " + colors )  
  7.   
  8. //  ++ 作为方法  
  9. colors = lang.++(colors)  
  10. println( "lang.++(colors)) : " + colors )  


打印结果为:

[java]  view plain  copy
  1. lang ++ colors : Map(blue -> #0033FF, C# -> Microsoft, yellow -> #FFFF00, Java -> Oracle, red -> #FF0000, Swift -> Apple)  
  2. lang.++(colors)) : Map(blue -> #0033FF, C# -> Microsoft, yellow -> #FFFF00, Java -> Oracle, red -> #FF0000, Swift -> Apple)  


输出 Map 的 keys 和 values

以下通过 foreach 循环输出 Map 中的 keys 和 values:

[java]  view plain  view plain copy
  1. val lang =Map("Java" -> "Oracle",  
  2.   "C#" -> "Microsoft",  
  3.   "Swift" -> "Apple")  
  4.   
  5. lang.keys.foreach{ i =>  
  6.   print( "Key = " + i )  
  7.   println("\tValue = " + lang(i) )}  

打印结果为:

[java]  view plain  copy
  1. Key = JavaValue = Oracle  
  2. Key = C#Value = Microsoft  
  3.   println("\tValue = " + lang(i) )}  

打印结果为:<

相关文章
相关标签/搜索