13 Collection 容器

这篇博客深入介绍了Scala的Collection框架,包括主要的collection特质、可变与不可变集合、序列Seq、列表、集Set以及常用操作方法。讨论了如何在Seq中添加或去除元素,强调了不可变集合在多线程环境中的安全性,并探讨了流、懒视图和并行collection的概念。还提到了转换方法如toXX和to[C],以及集合间的比较和运算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 官方collection教程
  • 所有collection扩展自Iterable特质
  • 三大类,序列,集合,映射 seq set map
  • 对于几乎所有的collection,都提供了可变和不可变的版本
  • 列表要么是空的,要么是一头一尾,尾是列表
  • 集合没有先后次序
  • + 将元素添加到无先后次序的容器中,+: 和 :+向前或向后追加到序列,++将两个集合串接到一起,-和–移除元素(1个减号和两个减号)
  • Iterable和Seq特质有数十个常见操作方法,很丰富
  • 映射、折叠和拉链

主要的collection特质

  • 下面请欣赏一组图片,注意蓝底白字(特质trait)和黑底白字(类class),虚线(隐式转换)和粗实线(默认实现)、细实线(通过类实现)图片来源
  • 首先是scala.collection
    在这里插入图片描述
  • scala.collection.immutable
    在这里插入图片描述
  • scala.collection.mutable
    在这里插入图片描述
  • 图例
    在这里插入图片描述
  • Iterable指的是那些能够交出用来访问集合中所有元素的Iterator的集合
val coll = List(2,1,4,3)  //任意Iterable特质的类
val iter = coll.iterator
while (iter.hasNext){
   println(iter.next())}
  • Seq是一个有先后次序的值的序列,例如数组或列表,IndexedSeq可以通过整型下标快速访问任意元素,ArrayBuffer带下标但链表不带。
  • Set是一组没有先后次序的值。
  • Map是一组键值的对偶。
  • 每一个collection特质或类都带有一个apply方法的伴生对象,这个apply方法可以用来构建collection中的实例。
  • 上面的三个图中出现的特质或类,统统可以直接拿来创建实例。图中粗实线是默认实现的关系,不管是Seq还是Iterable,默认的都是List
scala> Seq(1,2,3)
res1: Seq[Int] = List(1, 2, 3)

scala> Iterable(1,2,3)
res2: Iterable[Int] = List(1, 2, 3)
  • 不同collection之间的转换,可以调用toXX方法,和to[C]的泛型方法
scala> val list = List(1,2,3)
list: List[Int] = List(1, 2, 3)

scala> list.toVector
res5: Vector[Int] = Vector(1, 2, 3)

scala> list.to[Vector]
res6: Vector[Int] = Vector(1, 2, 3)
  • 使用==操作符实现任何seq、set、map的比较,如果不同类的collection比较,可以使用sameElements方法比较元素是否是相同。
scala> list == Vector(1,2,3)
res8: Boolean = true

scala> list == Set(1,2,3)
res9: Boolean = false

scala> list sameElements Set(1,2,3,2)
res10: Boolean = true

可变和不可变的collection

  • 不可变的collection可以安全共享引用,在多线程的应用程序中也无妨,scala.collection.Map, scala.collection.mutable.Map, scala.collection.immutable.Map,第一个是第二个和第三个的超类型
  • scala优先采用不可变集合,scala包和Predef对象里还有指向不可变特质的类型别名List、Set、Map。
  • 使用可变的,import scala.collection.mutable,然后使用mutable.Map就是可变的了。

序列Seq

  • 不可变的Seq
    在这里插入图片描述
  • 可变的Seq
    在这里插入图片描述
  • 对比上面两个图可以看出,不可变版的默认实现是Vector,可变版本的默认实现是ArrayBuffer。
  • Vector支持快速随机访问,是以树形结构的形式实现,每个节点可以有不超过32个子节点,速度很快
  • Range表示一个整数序列,只存储开始值、结束值、增值,可以使用to和until方法构造Range对象
  • 此外还有栈、队列、优先级队列等
scala> Range(1,10)
res16: scala.collection.immutable.Range = Range(1, 2, 3, 4, 5, 6, 7, 8, 9)

scala> Range(1,10,2)
res17: scala.collection.immutable.Range = Range(1, 3, 5, 7, 9)

scala> 1 until 10
res18: scala.collection.immutable.Range = Range(1, 2, 3, 4, 5, 6, 7, 8, 9)

scala> 1 to 10
res19: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
//栈
scala> val a =  collection.mutable.Stack(1,2,3)
a: scala.collection.mutable.Stack[Int] = Stack(1, 2, 3)
//入栈
scala> a.push(10)
res19: a.type = Stack(10, 1, 2, 3)
//出栈
scala> a.pop
res20: Int = 10

scala> a
res21: scala.collection.mutable.Stack[Int] = Stack(1, 2, 3)
//队列
scala> val b =  collection.mutable.Queue(1,2,3,4)
b: scala.collection.mutable.Queue[Int] = Queue(1, 2, 3, 4)
//入队
scala> b.enqueue(7)
//出队
scala> b.dequeue
res23: Int = 1

列表

  • 列表只有头和尾,head和tail,空列表Nil,head是第一个元素,tail是除了第一个元素以外的所有元素。
scala> val list = List(1,2,3,4)
list: List[Int] = List(1, 2, 3, 4)

scala> list.head
res24: Int = 1

scala> list.tail
res25: List[Int] = List(2, 3, 4)

scala> List(1).tail
res26: List[Int] = List()
  • 从给定的head和tail创建新列表 使用::操作符,这个操作符是右结合的,其右边需要是个List
scala> 100::list
res28: List[Int] = List(100, 1, 2, 3, 4)
//下面的错误
scala> list :: 100
<console>:13: error: value :: is not a member of Int
       list :: 100
       
scala> list ::list
res30: List[Any] = List(List(1, 2, 3, 4), 1, 2, 3, 4)
//使用递归访问列表,当然比较低效,下面的代码就出现了java.lang.StackOverflowError
def sum(lst:List[Int]):Double={
   
  if (lst == Nil) 0 else (lst.head * 1.0) + sum(lst.tail)
}
val a = (1 to 100000).toList
//使用模式匹配计算,同样的错误
def sum2(lst:List[Int]):Int=lst match{
   
  case Nil => 0
  case h :: t => h+sum2(t)
}
  • 可别版本的List使用ListBuffer,链表支撑的数据结构,高效地从任意一端添加或移除元素,但是添加或移除元素并不高效。

集 Set

  • Set是不重复的元素的collection,默认顺序是hashcode方法进行组织,这样查找元素比在数组或列表中更快
scala> val s = Set(1,2,3)
s: scala.collection.immutable.Set[Int] = Set(1, 2, 3)

scala> s+1
res34: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
  • 链式哈希set可以保留元素的插入顺序LinkedHashSet
//多参数
scala> Set(1 to 5: _*)
res8: scala.collection.immutable.Set[Int] = Set(5, 1, 2, 3, 4)

scala> for(i <- Set(1,2,3,4,5,6)) println(i)
5
1
6
2
3
4

scala>  val s1 = collection.mutable.LinkedHashSet(1,2,3,4,5,6)
s1: scala.collection.mutable.LinkedHashSet[Int] = Set(1, 2, 3, 4, 5, 6)

scala> for(i <- s1) println(i)
1
2
3
4
5
6

  • 已排序集合 SortedSet
scala> collection.mutable.SortedSet(5,1,3,2,4)
res11: scala.collection.mutable.SortedSet[Int] = TreeSet(1, 2, 3, 4, 5)
  • 位组集合,BitSet,以一个字符序列的方式存放非负整数,只能是正的Int型的,不能太大,也不能是其他类型的。如果位组中有i,那么低i个字位是1。
scala> collection.immutable.BitSet(1,2,3,2)
res35: scala.collection.immutable.BitSet = BitSet(1, 2, 3)

scala> collection.immutable.BitSet(1,2,2100000000)
java.lang.OutOfMemoryError: Java heap space
  • contains方法检查一个集合是不是包含某个元素,subsetOf方法检查某个集合是否被另一个集合包含
  • 集合的运算,交集、并集、差集,符号太麻烦,还是记忆union intersect diff简单
操作 方法 符号1 符号2
union | ++
intersect &
diff &~ --
scala> val s1 = Set(1,2,3)
s1: scala.collection.immutable.Set[Int] = Set(1, 2, 3)

scala> val s2 = Set(2,3,4)
s2: scala.collection.immutable.Set[Int] = Set(2, 3, 4)

scala> val s3 = Set(7,8)
s3: scala.collection.immutable.Set[Int] = Set(7, 8)

scala> s1.union(s2)
res38: scala.collection.immutable.Set[Int] = Set(1, 2, 3, 4)

scala> s1.intersect(s2)
res39: scala.collection.immutable.Set[Int] = Set(2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

独孤尚亮dugushangliang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值