1. Set 与 BitSet
Set(集合)是没有重复的对象集合,所有的元素都是唯一的。
Set(集合)分为可变的和不可变的集合。默认情况下,Scala 使用的是不可变集合,如果要使用可变集合,需要引用 scala.collection.mutable.Set 包。
BitSet(collection.immutable.BitSet)和Set类似,但操作更快。
BitSet代表一个由小整数构成的容器,这些小整数的值表示了一个大整数被置1的各个位。比如说,一个包含3、2和0的bit集合可以用来表示二进制数1101和十进制数13.
BitSet内部的使用了一个64位long型的数组。数组中的第一个long表示整数0到63,第二个表示64到27,以此类推。所以只要集合中最大的整数在千以内BitSet的压缩率都是相当高的。
BitSet操作的运行时间是非常快的。查找测试仅仅需要固定时间。向集合内增加一个项所需时间同BitSet数组中long型的个数成正比,但这也通常是个非常小的值。
1.1 Set 初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| val set1 = Set(1,2,3,4,5) println(set1)
import scala.collection.mutable val set2 = mutable.Set(1,3,9,6,14,5,2,1) println(set2)
val words = mutable.Set.empty[String]
val bitSet1 = collection.immutable.BitSet(1,2,3,3,2,1) println(bitSet1)
val bitSet2 = collection.mutable.BitSet(1,2,3,3,2,1) println(bitSet2)
|
1.2 Set 查看元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| val set1 = Set(1, 2, 3, 4, 5) println(set1)
println(set1.size) println(set1.head) println(set1.last) println(set1.sum) println(set1.max) println(set1.min)
println(set1(3)) println(set1(0))
|
1.3 Set 增加元素
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
| import scala.collection.mutable val set1 = mutable.Set(1,2,3)
set1 += 4 println(set1) set1 += (5,6) println(set1)
val set2 = set1 ++ Set(7,8) println(set2)
set1.add(9) println(set1)
val set3 = mutable.Set(1,2,3) val set4 = set3 ++ Set(2,3,4) println(set4)
val set5 = Set(1,2,3) ++ Set(2,3,4) println(set5)
println("123")
val bitSet1 = collection.mutable.BitSet() bitSet1 += (1,3,5) println(bitSet1)
bitSet1 ++= Set(7,9) println(bitSet1)
|
1.4 Set 删除元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import scala.collection.mutable val set1 = mutable.Set(1,2,3,4,5,6,7)
val set2 = set1 - 1 println(set2) val set3 = set2 - (3,2) println(set3)
val set4 = set3 --= Set(4,5) println(set4)
set4.empty println(set4)
val set5 = Set(1,2,3) -- Set(2,3,4) println(set5)
|
1.5 set 交并补集
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
| val set1 = Set(1,2,3,4) val set2 = Set(3,4,5,6)
val set3 = set1 & set2 println(set3)
val set4 = set1.intersect(set2) println(set4)
val set5 = set1 | set2 println(set5)
val set6 = set1 union set2 println(set6)
val set7 = set1 &~ set2 println(set7)
val set8 = set1 diff set2 println(set8)
|
2. Tuple (元组)
Tuple是一个可以容纳不同类型元素的类。
Tuple是不可变的(长度固定,元素不可变),常用于有多个返回值的函数,或者多个变量的同时定义。
Tuple使用括号来表示”()”,获取元组中的值使用下划线表示,下标从1开始
2.1 Tuple 初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| val t1 = ("小明", "男", 18) println(t1) println(t1.getClass())
println(t1._1) println(t1._2) println(t1._3)
val t2 = ("id",123) println(t2._1) println(t2._2)
val tuple3,(name,age,sex)=("小明",18,"男") println(name) println(age) println(sex)
|
2.7 Tuple 其他操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| val numPairs = List((2, 5), (3, -7), (20, 56))
for ((a, b) <- numPairs) {
println(a * b)
}
|
3. Vector(向量)
Vector类型的构建和修改与其他的序列结构基本一样。
对于只需要处理数据结构头结点的算法来说,List非常高效。可是相对于访问、添加和删除List头结点只需要固定时间,访问和修改头结点之后元素所需要的时间则是与List深度线性相关的。
Vector(向量)是用来解决list不能高效的随机访问的一种结构。Vector结构能够在“更高效”的固定时间内访问到列表中的任意元素。虽然这个时间会比访问头结点或者访问某数组元素所需的时间长一些,但至少这个时间也是个常量。因此,使用Vector的算法不必仅是小心的处理数据结构的头结点。由于可以快速修改和访问任意位置的元素,所以对Vector结构做写操作很方便。
Vector结构通常被表示成具有高分支因子的树(树或者图的分支因子是指数据结构中每个节点的子节点数目)。每一个树节点包含最多32个vector元素或者至多32个子树节点。包含最多32个元素的vector可以表示为一个单一节点,而一个间接引用则可以用来表示一个包含至多32*32=1024个元素的vector。从树的根节点经过两跳到达叶节点足够存下有2的15次方个元素的vector结构,经过3跳可以存2的20次方个,4跳2的25次方个,5跳2的30次方个。所以对于一般大小的vector数据结构,一般经过至多5次数组访问就可以访问到指定的元素。这也就是我们之前所提及的随机数据访问时“运行时间的相对高效”。
3.1 Vector 初始化
1 2 3 4 5 6 7 8 9 10 11 12
| val v1 = scala.collection.immutable.Vector.empty println(v1)
val v2 = collection.immutable.IndexedSeq(1, 2, 3) println(v2)
val v3 = Vector(1,2,3,4,5) println(v3)
val v4 = Vector(1 to 3:_*) println(v4)
|
3.2 Vector 查看元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| val v1 = Vector(1,2,3,4,5)
println(v1(0))
println(v1.take(2))
println(v1.max) println(v1.min)
v1.map(v => { println(v) })
v1.map(println(_))
println(v1.length) println(v1.size)
|
3.3 Vector 增加元素
Vector 是不可变的,不能增加长度,可以将元素追加生成一个新的Vector
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
| val v1 = Vector(1,2) println(v1)
val v2 = v1 :+ 3 :+ 4
println(v2) println(v2.getClass)
val v3 = v1 ++:Vector(3,4) println(v3)
val v4 = v1.++(Vector(3,4)) println(v4)
val v5 = -1 +: 0 +: v1 println(v5)
val v6 = Vector(-1,0) ++: v1 println(v6)
val v7 = Vector(-1,0).++(v1) println(v7)
|
3.4 Vector 修改元素
1 2 3 4 5 6 7 8 9 10 11
| val v1 = Vector(1, 2, 3) println(v1)
v1(0)=100
val v2 = v1.updated(0,100) println(v2)
|
从上面例子的最后一行我们可以看出,update方法的调用并不会改变vec的原始值。与元素访问类似,vector的update方法的运行时间也是“相对高效的固定时间”。对vector中的某一元素进行update操作可以通过从树的根节点开始拷贝该节点以及每一个指向该节点的节点中的元素来实现。这就意味着一次update操作能够创建1到5个包含至多32个元素或者子树的树节点。当然,这样做会比就地更新一个可变数组败家很多,但比起拷贝整个vector结构还是绿色环保了不少。
由于vector在快速随机选择和快速随机更新的性能方面做到很好的平衡,所以它目前正被用作不可变索引序列的默认实现方式。
3.6 Vector 元素排序
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
| val v1 = Vector(3, 1, 5, 4, 7, 6, 9)
val v2 = v1.sorted println(v2.toBuffer)
val v3 = v1.sorted.reverse println(v3.toBuffer)
val v4 = v1.sortBy(a => a) println(v4.toBuffer)
val v5 = v1.sortBy(a => a).reverse println(v5.toBuffer)
val v6 = v1.sortWith(_ < _) println(v6.toBuffer)
val v7 = v1.sortWith(_ > _) println(v7.toBuffer)
|
3.7 Vector 其他操作
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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| val v1 = Vector[Int](1, 2, 3)
println(v1.contains(1)) println(v1.contains(11))
val str: String = v1.mkString(",") println(str)
val str2 = v1.mkString("[", ",", "]") println(str2)
val v2 = v1.drop(2) println(v2.toBuffer)
val v3 = v1.reverse println(v3.toBuffer)
val v4 = Vector(1,3,2,5,4) v4 .map((x:Int)=>x*2) .sortBy((x:Int)=>x) .reverse .foreach(println(_))
v4.map(_*2).sortBy(x=>x).reverse.foreach(println)
val strVector = Vector("hello you","hello world")
val strVector2 = strVector .map(x=>{ val fields = x.split(" ") fields }).flatten
println(strVector2.toBuffer)
val strVector3 = strVector.flatMap(x=>x.split(" ")) println(strVector3.toBuffer)
val strVector4 = strVector.flatMap(_.split(" ")).distinct println(strVector4)
|
4. Stack
如果您想要实现一个后入先出的序列,那您可以使用Stack。您可以使用push向栈中压入一个元素,用pop从栈中弹出一个元素,用top查看栈顶元素而不用删除它。所有的这些操作都仅仅耗费固定的运行时间。
ArrayStack 是另一种可变栈的实现,用一个可根据需要改变大小的数组做为支持。它提供了快速索引,使其通常在大多数的操作中会比普通的可变堆栈更高效一点。
4.1 Stack 初始化
1 2 3 4 5 6 7 8 9 10
| val s1 = scala.collection.immutable.Stack.empty println(s1)
val s2 = immutable.Stack(1,2,3) println(s2)
val s3 = mutable.Stack(1 to 5:_*) println(s3)
|
4.2 Stack 查看元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| val s1 = mutable.Stack(1 to 5:_*) println(s1)
val s2 = s1.filter(_>3) println(s2)
println(s1.top)
println(s1(0)) println(s1.max) println(s1.min) println(s1.length)
|
4.3 Stack 增加元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| val s1 = new scala.collection.mutable.Stack[Int] println(s1)
s1.push(1) println(s1)
s1.push(2) println(s1)
s1.push(3,4,5) println(s1)
val s5 = mutable.Stack(1,2) val s6 = mutable.Stack(3,4)
val s7 = s5.++:(s6) println(s7)
|
4.4 Stack 修改元素
1 2 3 4 5 6 7 8 9 10
| val s1 = mutable.Stack(1 to 5:_*)
s1(0)=10 println(s1)
s1.update(1,20) println(s1)
val s2 = s1.updated(2,30) println(s2)
|
4.5 Stack 删除元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| val s1 = mutable.Stack(1 to 5:_*) println(s1)
s1.pop() println(s1)
val s2 = s1.drop(2) println(s2)
s1.clear() println(s1)
|
5. Queue
Queue是一种与stack很相似的数据结构,除了与stack的后入先出不同,Queue结构的是先入先出的。
Scala除了提供了可变与不可变的Queue。你需要使用+= 和++=操作符进行添加的方式来替代排队方法。 在一个可变队列中,出队方法将只移除头元素并返回该队列。
5.1 Queue 初始化
1 2 3 4 5 6 7 8 9 10 11
| val q1 = new scala.collection.mutable.Queue[String] println(q1)
val q2 = Queue(1,2,3) println(q2)
val q3 = scala.collection.immutable.Queue(4,5,6) println(q3)
val q4 = Queue(1 to 5:_*) println(q4)
|
5.2 Queue 查看元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| val q1 = Queue(1 to 5:_*) println(q1)
println(q1.head)
val s2 = q1.filter(_>3) println(s2)
println(q1.dequeue()) println(q1)
println(q1(0)) println(q1.max) println(q1.min) println(q1.length)
|
5.3 Queue 增加元素
1 2 3 4 5 6 7 8 9 10
| val q1 = Queue(1 to 3:_*)
val q2 = q1.++:(Queue(4)) println(q2)
val q3 = q1.++(Queue(2,3)) println(q3)
|
5.4 Queue 修改元素
1 2 3 4
| val q1 = scala.collection.immutable.Queue(1 to 3: _*) val q2 = q1.updated(0,10) println(q2)
|
5.5 Queue 删除元素
1 2 3 4 5 6 7 8 9 10
| val q1 = Queue(1 to 5: _*)
val q2 = q1.drop(2) println(q2)
val q3 = q2.diff(Queue(3,4,6)) println(q3)
|
6. Stream
流Stream与List很相似,只不过其中的每一个元素都经过了一些简单的计算处理。也正是因为如此,stream结构可以无限长。只有那些被要求的元素才会经过计算处理,除此以外stream结构的性能特性与List基本相同。
List通常使用 :: 运算符来进行构造,stream使用外观上很相像的#::。
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
| val s1 = Stream.range(1,1000000000) println(s1) val s2 = 1 #:: 2 #:: 3 #:: Stream.empty println(s2)
val fibs = fibFrom(1, 1).take(7) println(fibs.toList)
def fibFrom(a: Int, b: Int): Stream[Int] = { a #:: fibFrom(b, a + b) }
|
7. Iterator(迭代器)
迭代器不是一个容器,更确切的说是逐一访问容器内元素的方法。迭代器Iterator的两个基本操作是next和hasNext。调用it.next()会返回迭代器的下一个元素,并且更新迭代器的状态。在同一个迭代器上再次调用next,会产生一个新元素来覆盖之前返回的元素。如果没有元素可返回,调用next方法会抛出一个NoSuchElementException异常。你可以调用迭代器的hasNext方法来查询容器中是否有下一个元素可供返回。
7.1 Iterator 初始化
1 2 3 4 5 6
| val it1 = Iterator("a", "number", "of", "words") println(it1)
val (a,b) = Iterator(1,3,5,7) duplicate
|
7.2 Iterator 遍历元素
1 2 3 4 5 6 7 8 9 10 11
| val it1 = Iterator("a", "number", "of", "words")
while (it1.hasNext){ print(it1.next()+"\t") }
println(it1.hasNext)
println(it1.next())
|
1 2 3 4
| for(e<- Iterator(1,3,5,7)) { println(e) }
|
1
| Iterator(1,3,5,7) foreach println
|
1 2
| val list1 = (Iterator(1,3,5,7) map (1*) toList) println(list1)
|
1 2
| val list2 = (Iterator(1,3,5,7) dropWhile (5>) toList) println(list2)
|