Scala的Iterable、Seq、Set、Map集合
1. Iterable
1.1 概述
Iterable代表一个可以迭代的集合,它继承了Traversable特质,同时也是其他集合的父特质。最重要的是,它定义了获取迭代器(iterator)的方法:def iterator:Iterator[A]
,这是一个抽象方法,它的具体实现类需要实现这个方法,从而实现迭代的返回集合中的元素
1.2 分类
Traversable提供了两种遍历数据的方式:
iterator()
方法:属于主动迭代,我们可以通过hasNext()检查是否还有元素,并且可以主动地调用next()方法获取元素,即我们可以自主地控制迭代过程foreach()
方法:属于被动迭代,我们只提供一个函数,并不能控制遍历的过程,即迭代过程是由集合本身控制的
1.3 遍历集合
示例:
object ClassDemo {
def main(args:Array[String]):Unit = {
//1.定义一个列表
val list = (1 to 5).toList
//2.通过iterator()方法遍历
//2.1通过集合对象(list)来获取其对应的迭代器对象
val it:Iterator[Int] = list.iterator
//2.2判断是否还有下一个元素,因为不知道集合中有多少个元素,所以采用循环来实现
while (it.hasNext) {
//只要能走到这里,说明集合中有元素
//2.3通过next()方法来获取指定的元素
val num = it.next()
println(num)
}
//3.通过foreach()方法遍历
//普通版
list.foreach((x:Int) => println(x))
//优化版
list.foreach(println(_))
}
}
//1
//2
//3
//4
//5
1.4 分组遍历
如果遇到将Iterable对象中的元素分成固定大小的组,然后遍历这种需求,就可以通过grouped()
方法实现。
格式:
def grouped(size:Int):Iterator[Iterable[A]]
示例:
object ClassDemo {
def main(args:Array[String]):Unit = {
//1.定义一个Iterable集合
val list = (1 to 13).toIterable
//2.对Iterable集合分组
//方式一:合并版(推荐)
//2.1获取迭代器对象
val it = list.grouped(5)
//2.2判断迭代器中是否有元素
while (it.hasNext) {
//2.3如果有,则获取元素,并打印
val result = it.next()
println(result)
}
//方式二:分解版
//第一次获取
val b1 = it.hasNext
if (b1) {
val.result1 = it.next()
println(b1, result1) //(true, Vecotr(1,2,3,4,5))
//第二次获取
val b2 = it.hasNext
if (b2) {
val.result2 = it.next()
println(b2, result2) //(true, Vecotr(6,7,8,9,10))
//第三次获取
val b3 = it.hasNext
if (b3) {
val.result3 = it.next()
println(b3, result3) //(true, Vecotr(11,12,13))
}
}
}
//Vecotr(1,2,3,4,5)
//Vecotr(6,7,8,9,10)
//Vecotr(11,12,13)
1.5 按照索引生成元组
Iterable集合中存储的每个元素都是有索引的,如果我们想按照元素 -> 索引
这种格式,生成一个新的集合,此时需要用到zipWithIndex()
方法。
示例:
object ClassDemo {
def main(args:Array[String]):Unit = {
//1.定义一个Iterable集合
val list1 = Iterable("A", "B", "C", "D", "E")
//2.通过zipWithIndex()方法,按字符串->索引这种格式,生成新的集合
val list2:Iterable[(String, Int)] = list1.zipWithIndex
//3.重新按照 索引->字符串这种格式,生成新的集合
val list3:Iterable[(Int, String)] = list2.map(x => x._2 -> x._1)
//4.打印结果
list3.foreach(println(_))
}
}
//(0,A)
//(1,B)
//(2,C)
//(3,D)
//(4,E)
1.6 判断集合是否相同
有时,我们不仅想判断两个集合中的元素是否全部相同,而且要求这两个集合元素的迭代顺序保持一致,此时用sameElements()
方式实现
示例:
object ClassDemo {
def main(args:Array[String]):Unit = {
//1.定义一个Iterable集合
val list1 = Iterable("A", "B", "C")
//2.通过sameElements()方法,判断list1和Iterable("A", "B", "C")集合是否相同
println(list1.sameElements(Iterable("A", "B", "C"))) //true
//3.通过sameElements()方法,判断list1和Iterable("A", "C", "B")集合是否相同
println(list1.sameElements(Iterable("A", "C", "B"))) //false
//4.通过sameElements()方法,判断list1和list2是否相同
val list2 = Iterable("A", "B", "C", "D")
println(list1.sameElements(list2))) //false
}
}
//
2. Seq
2.1 概述
Seq特质代表按照一定顺序排列的元素序列,序列是一种特别的可迭代集合,它的元素特点是有序(元素存取顺序一致),可重复,有索引
2.2 分类
2.3 创建Seq集合
示例:
object ClassDemo {
def main(args:Array[String]):Unit = {
val s1 = (1 to 5).toSeq
print(s1)
}
}
//Range(1,2,3,4,5)
2.4 获取长度及元素
因为Seq集合的每个元素都是有索引的,所以我们可以通过索引直接获取其对应的元素,而且通过length()
或size()
方法获取集合的长度
示例:
object ClassDemo {
def main(args:Array[String]):Unit = {
val s1 = (1 to 5).toSeq
//打印长度
println(s1.length, s1.size) //(5, 5)
//获取索引为2的元素
//方式一:通过集合名(索引)的方式实现
println(s1(2)) //3
//方式二:通过集合的伴生对象的apply()方法实现
println(s1.apply(2)) //3
}
}
2.5 获取指定元素的索引值
格式:
示例:
object ClassDemo {
def main(args:Array[String]):Unit = {
val s1 = Seq(1, 2, 4, 6, 4, 3, 2)
println(s1.indexOf(2)) //1
println(s1.lastIndexOf(2)) //6
println(s1.indexWhere(x => x < 5 && x % 2 == 0)) //1
println(s1.indexWhere(x => x < 5 && x % 2 == 0, 2)) //4
println(s1.lastIndexWhere(x => x < 5 && x % 2 == 0)) //6
println(s1.indexOfSlice(Seq(1,2))) //0
println(s1.indexOfSlice(Seq(1,2), 3)) //-1
}
}
2.6 判断是否包含指定数据
格式:
示例:
object ClassDemo {
def main(args:Array[String]):Unit = {
val s1 = (1 to 10).toSeq
println(s1.startsWith(Seq(1,2))) //true
println(s1.startsWith(Seq(1,3))) //false
println(s1.endsWith(Seq(9,10))) //true
println(s1.endsWith(Seq(8,9))) //false
println(s1.contains(3) //true
println(s1.containsSlice(Seq(1,2))) //true
println(s1.containsSlice(Seq(1,3))) //false
}
}
2.7 修改指定的元素
格式:
示例:
object ClassDemo {
def main(args:Array[String]):Unit = {
val s1 = (1 to 5).toSeq
println(s1) //Range(1,2,3,4,5)
val s2 = s1.update(2, 10)
println(s2) //Vector(1,2,10,4,5)
/*
第一个参数:起始索引
第二个参数:替换后的元素
第三个参数:替换几个
*/
val s3 = s1.patch(1, Seq(10, 20), 3)
println(s3) //Vector(1,10,20,5)
}
}
3. Stack
3.1 概述
栈的元素特点是先进后出。由于历史原因,Scala当前的库中还包含一个immutable.Stack
,但当前已标记为弃用,因为设计不优雅且性能不佳。因为栈设计大量元素的进出,常用的还是可变栈,例如mutable.Stack
, mutable.ArrayStack
3.2 常用方法
3.3 演示Stack可变栈
示例:
import scala.collection.mutable
object ClassDemo {
def main(args:Array[String]):Unit = {
val s1 = mutable.Stack(1,2,3,4,5)
println(s1) //Stack(1,2,3,4,5)
println(s1.top) //1
println(s1.push(6)) //Stack(6,1,2,3,4,5)
println(s1.pushAll(Seq(11,22,33))) //Stack(33,22,11,6,1,2,3,4,5)
println(s1.pop()) //33
s1.clear()
println(s1) //stack()
}
}
3.4 演示ArrayStack可变栈
示例:
import scala.collection.mutable
object ClassDemo {
def main(args:Array[String]):Unit = {
val s1 = mutable.ArrayStack(1,2,3,4,5)
println(s1) //ArrayStack(1,2,3,4,5)
s1.dup()
println(s1) //ArrayStack(1,1,2,3,4,5)
s1.preserving({
//当该方法中的内容执行完毕后,栈中的数据会恢复
s1.clear()
println('hi')
}) //hi
println(s1) //ArrayStack(1,2,3,4,5)
}
}
4. Queue
4.1 概述
队列的元素特点是先进先出,常用的队列是可变队列:mutable.Queue,它内部是以MutableList数据结构实现的。
4.2 常用方法
示例:
import scala.collection.mutable
object ClassDemo {
def main(args:Array[String]):Unit = {
val q1 = mutable.Queue(1,2,3,4,5)
println(q1) //Queue(1,2,3,4,5)
q1.enqueue(6)
println(q1) //Queue(1,2,3,4,5,6)
q1.enqueue(7,8,9)
println(q1) //Queue(1,2,3,4,5,6,7,8,9)
println(q1.dequeue()) //1
println(q1.dequeueFirst(_ % 2 != 0)) //Some(3)
println(q1.dequeueAll(_ % 2 == 0)) //ArrayBuffer(2,4,6,8)
println(q1) //Queue(5,7,9)
}
}
5. Set
5.1 概述
Set集合中的元素不包含重复的元素
5.2 分类
示例:
import scala.collection.{SortedSet, mutable}
object ClassDemo {
def main(args:Array[String]):Unit = {
val s1 = SortedSet(1,4,3,2,5)
println(s1) //TreeSet(1,2,3,4,5)
val s2 = mutable.HashSet(1,4,3,2,5)
println(s2) //Set(1,5,2,3,4)
val s3 = mutale.LinkedHashSet(1,4,3,2,5)
println(s3) //Set(1,4,3,2,5)
}
}
6. Map
6.1 概述
Map表示映射,包含键值对的集合,基本操作类似于Set集合的操作。
6.2 分类
示例:
import scala.collection.{SortedSet, mutable}
object ClassDemo {
def main(args:Array[String]):Unit = {
val m1 = Map('A' -> 1, 'B' -> 2, 'C' -> 3)
//遍历
//方式一:通过普通for循环实现
for((k,v) <- map) println(k,v)
//(A,1)
//(B,2)
//(C,3)
//方式二:通过foreach函数实现
map.foreach(println(_))
//(A,1)
//(B,2)
//(C,3)
println(map.filterKeys(_ == 'B')) //Map(B -> 2)
}
}
7. 案例:统计字符个数
需求:
步骤:
import scala.collection.mutable
import scala.io.StdIn
object ClassDemo {
def main(args:Array[String]):Unit = {
//1.提示用户录入字符串,并接收
println('请录入一个字符串:')
val str = StdIn.readLine()
//2.定义Map集合,用来存储字符及其出现的次数
val map = mutable.Map[Char, Int]()
//3.将字符串转成字符数组
val chs = str.toCharArray
//4.遍历字符数组,获取每一个字符
for(k <- chs) {
//5.1如果字符是第一次出现,就将其次数记录为1
if (map.contains(k)) {
map += (k -> 1)
} else {
//5.2如果字符是重复出现,就将其次数+1,然后重新存储
map += (k -> (map.getOrElse(k, 1) + 1))
}
}
//6.遍历集合,查看结果
map.foreach(println(_))
}
}