- 测试型的方法:,
apply
,subsetOf
。contains
方法用于判断集合是否包含某元素。集合的apply
方法和contains
方法的作用相同,因此set(elem)
等同于set contains elem
。这意味着集合对象的名字能作为其自身是否包含某元素的测试函数。例如
- 加法类型的方法:
+
和++
。添加一个或多个元素到集合中,产生一个新的集合。 - 减法类型的方法:
-
、—
。它们实现从一个集合中移除一个或多个元素,产生一个新的集合。
可变集合提供加法类方法,可以用来添加、删除或更新元素。下面对这些方法做下总结。
WHAT IT IS | WHAT IT DOES |
---|---|
加法: | |
xs += x | 把元素 x 添加到集合 xs 中。该操作有副作用,它会返回左操作符,这里是 xs 自身。 |
xs += (x, y, z) | 添加指定的元素到集合 xs 中,并返回 xs 本身。(同样有副作用) |
xs ++= ys | 添加集合 ys 中的所有元素到集合 xs 中,并返回 xs 本身。(表达式有副作用) |
xs add x | 把元素 x 添加到集合 xs 中,如集合 xs 之前没有包含 x ,该操作返回 true ,否则返回 false 。 |
移除: | |
xs -= x | 从集合 xs 中删除元素 x ,并返回 xs 本身。(表达式有副作用) |
xs -= (x, y, z) | 从集合 xs 中删除指定的元素,并返回 xs 本身。(表达式有副作用) |
xs —= ys | 从集合 xs 中删除所有属于集合 ys 的元素,并返回 xs 本身。(表达式有副作用) |
xs remove x | 从集合 xs 中删除元素 x 。如之前 xs 中包含了 x 元素,返回 true ,否则返回 false 。 |
xs retain p | 只保留集合 xs 中满足条件 p 的元素。 |
xs.clear() | 删除集合 xs 中的所有元素。 |
更新: | |
xs(x) = b | ( 同 xs.update(x, b) )参数 b 为布尔类型,如果值为 true 就把元素x加入集合 xs ,否则从集合 xs 中删除 x 。 |
克隆: | |
xs.clone | 产生一个与 xs 具有相同元素的可变集合。 |
与不变集合一样,可变集合也提供了+
和++
操作符来添加元素,和—
用来删除元素。但是这些操作在可变集合中通常很少使用,因为这些操作都要通过集合的拷贝来实现。可变集合提供了更有效率的更新方法,+=
和-=
。 s += elem
,添加元素elem到集合s中,并返回产生变化后的集合作为运算结果。同样的,s -= elem
执行从集合s中删除元素elem的操作,并返回产生变化后的集合作为运算结果。除了+=
和-=
之外还有从可遍历对象集合或迭代器集合中添加和删除所有元素的批量操作符++=
和—=
。
选用+=
和-=
这样的方法名使得我们得以用非常近似的代码来处理可变集合和不可变集合。先看一下以下处理不可变集合 s
的REPL会话:
scala> var s = Set(1, 2, 3)
s: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
scala> s += 4
scala> s -= 2
scala> s
res2: scala.collection.immutable.Set[Int] = Set(1, 3, 4)
我们在immutable.Set
类型的变量中使用+=
和-=
。诸如 s += 4
的表达式是 s = s + 4
的缩写,它的作用是,在集合 s
上运用方法+
,并把结果赋回给变量 s
。下面我们来分析可变集合上的类似操作。
最后结果看起来和之前的在非可变集合上的操作非常相似;从Set(1, 2, 3)
开始,最后得到Set(1, 3, 4)
。然而,尽管相似,但它们在实现上其实是不同的。 这里s += 4
是在可变集合值s上调用+=
方法,它会改变 s
的内容。同样的,s -= 2
也是在s上调用 -=
方法,也会修改 s
集合的内容。
可变集合同样提供作为 +=
和 -=
的变型方法,add
和 remove
,它们的不同之处在于 add
和 remove
会返回一个表明运算是否对集合有作用的Boolean值
目前可变集合默认使用哈希表来存储集合元素,非可变集合则根据元素个数的不同,使用不同的方式来实现。空集用单例对象来表示。元素个数小于等于4的集合可以使用单例对象来表达,元素作为单例对象的字段来存储。 元素超过4个,非可变集合就用哈希前缀树(hash trie)来实现。
采用这种表示方法,较小的不可变集合(元素数不超过4)往往会比可变集合更加紧凑和高效。所以,在处理小尺寸的集合时,不妨试试不可变集合。
集合的两个特质是 SortedSet
和 BitSet
。
SortedSet 是指以特定的顺序(这一顺序可以在创建集合之初自由的选定)排列其元素(使用iterator或foreach)的集合。 的默认表示是有序二叉树,即左子树上的元素小于所有右子树上的元素。这样,一次简单的顺序遍历能按增序返回集合中的所有元素。Scala的类 immutable.TreeSet
使用红黑树实现,它在维护元素顺序的同时,也会保证二叉树的平衡,即叶节点的深度差最多为1。
myOrdering: scala.math.Ordering[String] = ...
然后,用这一排序规则创建一个空的树集:
或者,你也可以不指定排序规则参数,只需要给定一个元素类型或空集合。在这种情况下,将使用此元素类型默认的排序规则。
scala> TreeSet.empty[String]
res2: scala.collection.immutable.TreeSet[String] = TreeSet()
如果通过已有的TreeSet来创建新的集合(例如,通过串联或过滤操作),这些集合将和原集合保持相同的排序规则。例如,
有序集合同样支持元素的范围操作。例如,range方法返回从指定起始位置到结束位置(不含结束元素)的所有元素,from方法返回大于等于某个元素的所有元素。调用这两种方法的返回值依然是有序集合。例如:
scala> res3 range ("one", "two")
res4: scala.collection.immutable.TreeSet[String] = TreeSet(one, three)
scala> res3 from "three"
位集合是由单字或多字的紧凑位实现的非负整数的集合。其内部使用 Long
型数组来表示。第一个 Long
元素表示的范围为0到63,第二个范围为64到127,以此类推(值为0到127的非可变位集合通过直接将值存储到第一个或第两个 Long
字段的方式,优化掉了数组处理的消耗)。对于每个 Long
,如果有相应的值包含于集合中则它对应的位设置为1,否则该位为0。这里遵循的规律是,位集合的大小取决于存储在该集合的最大整数的值的大小。假如N是为集合所要表示的最大整数,则集合的大小就是 N/64
个长整形字,或者 N/8
个字节,再加上少量额外的状态信息字节。