scala基础---集合操作汇总

来源:互联网 发布:四等水准仪测量数据 编辑:程序博客网 时间:2024/05/22 00:14

集合


集合是不包含重复元素的可迭代对象。下面的通用集合表和可变集合表中概括了集合类型适用的运算。分为几类:

  • 测试型的方法:contains,apply,subsetOf。contains方法用于判断集合是否包含某元素。集合的apply方法和contains方法的作用相同,因此 set(elem) 等同于set constains elem。这意味着集合对象的名字能作为其自身是否包含某元素的测试函数。

例如

  1. val fruit = Set("apple", "orange", "peach", "banana")
  2. fruit: scala.collection.immutable.Set[java.lang.String] =
  3. Set(apple, orange, peach, banana)
  4. scala> fruit("peach")
  5. res0: Boolean = true
  6. scala> fruit("potato")
  7. res1: Boolean = false
  • 加法类型的方法: + 和 ++ 。添加一个或多个元素到集合中,产生一个新的集合。
  • 减法类型的方法: - 、–。它们实现从一个集合中移除一个或多个元素,产生一个新的集合。
  • Set运算包括并集、交集和差集。每一种运算都存在两种书写形式:字母和符号形式。字母形式:intersect、union和diff,符号形式:&、和&~。事实上,Set中继承自Traversable的++也能被看做union或的另一个别名。区别是,++的参数为Traversable对象,而union和的参数是集合。

Set 类的操作

WHAT IT ISWHAT IT DOES 实验代码:  xs contains x测试x是否是xs的元素。 xs(x)与xs contains x相同。 xs subsetOf ys测试xs是否是ys的子集。 加法:  xs + x包含xs中所有元素以及x的集合。 xs + (x, y, z)包含xs中所有元素及附加元素的集合 xs ++ ys包含xs中所有元素及ys中所有元素的集合 实验代码:  xs - x包含xs中除x以外的所有元素的集合。 xs - x包含xs中除去给定元素以外的所有元素的集合。 xs – ys集合内容为:xs中所有元素,去掉ys中所有元素后剩下的部分。 xs.empty与xs同类的空集合。 二值操作:  xs & ys集合xs和ys的交集。 xs intersect ys等同于 xs & ys。 xsys集合xs和ys的并集。xs union ys等同于xsys。xs &~ ys集合xs和ys的差集。 xs diff ys等同于 xs &~ ys。 

可变集合提供加法类方法,可以用来添加、删除或更新元素。下面对这些方法做下总结。

mutable.Set 类的操作

WHAT IT ISWHAT 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会话:

  1. scala> var s = Set(1, 2, 3)
  2. s: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
  3. scala> s += 4
  4. scala> s -= 2
  5. scala> s
  6. res2: scala.collection.immutable.Set[Int] = Set(1, 3, 4)

我们在immutable.Set类型的变量中使用+=-= 。诸如 s += 4 的表达式是 s = s + 4 的缩写,它的作用是,在集合s上运用方法+,并把结果赋回给变量s。下面我们来分析可变集合上的类似操作。

  1. scala> val s = collection.mutable.Set(1, 2, 3)
  2. s: scala.collection.mutable.Set[Int] = Set(1, 2, 3)
  3. scala> s += 4
  4. res3: s.type = Set(1, 4, 2, 3)
  5. scala> s -= 2
  6. res4: s.type = Set(1, 4, 3)

最后结果看起来和之前的在非可变集合上的操作非常相似;从Set(1, 2, 3)开始,最后得到Set(1, 3, 4)。然而,尽管相似,但它们在实现上其实是不同的。 这里s += 4 是在可变集合值s上调用+=方法,它会改变s的内容。同样的,s -= 2 也是在s上调用 -= 方法,也会修改s集合的内容。

通过比较这两种方式得出一个重要的原则。我们通常能用一个非可变集合的变量来替换可变集合的常量,反之亦然。这一原则至少在没有别名的引用添加到Collection时起作用。别名引用主要是用来观察操作在Collection上直接做的修改还是生成了一个新的Collection。

可变集合同样提供作为+=-=的变型方法,add和remove,它们的不同之处在于add和remove会返回一个表明运算是否对集合有作用的Boolean值

目前可变集合默认使用哈希表来存储集合元素,非可变集合则根据元素个数的不同,使用不同的方式来实现。空集用单例对象来表示。元素个数小于等于4的集合可以使用单例对象来表达,元素作为单例对象的字段来存储。 元素超过4个,非可变集合就用哈希前缀树(hash trie)来实现。

采用这种表示方法,较小的不可变集合(元素数不超过4)往往会比可变集合更加紧凑和高效。所以,在处理小尺寸的集合时,不妨试试不可变集合。

集合的两个特质是SortedSet和 BitSet。

有序集(SortedSet)

SortedSet 是指以特定的顺序(这一顺序可以在创建集合之初自由的选定)排列其元素(使用iterator或foreach)的集合。 SortedSet 的默认表示是有序二叉树,即左子树上的元素小于所有右子树上的元素。这样,一次简单的顺序遍历能按增序返回集合中的所有元素。Scala的类 immutable.TreeSet使用红黑树实现,它在维护元素顺序的同时,也会保证二叉树的平衡,即叶节点的深度差最多为1。

创建一个空的 TreeSet ,可以先定义排序规则:

  1. scala> val myOrdering = Ordering.fromLessThan[String](_ > _)
  2. myOrdering: scala.math.Ordering[String] = ...

然后,用这一排序规则创建一个空的树集:

  1. scala> TreeSet.empty(myOrdering)
  2. res1: scala.collection.immutable.TreeSet[String] = TreeSet()

或者,你也可以不指定排序规则参数,只需要给定一个元素类型或空集合。在这种情况下,将使用此元素类型默认的排序规则。

  1. scala> TreeSet.empty[String]
  2. res2: scala.collection.immutable.TreeSet[String] = TreeSet()

如果通过已有的TreeSet来创建新的集合(例如,通过串联或过滤操作),这些集合将和原集合保持相同的排序规则。例如,

  1. scala> res2 + ("one", "two", "three", "four")
  2. res3: scala.collection.immutable.TreeSet[String] = TreeSet(four, one, three, two)

有序集合同样支持元素的范围操作。例如,range方法返回从指定起始位置到结束位置(不含结束元素)的所有元素,from方法返回大于等于某个元素的所有元素。调用这两种方法的返回值依然是有序集合。例如:

  1. scala> res3 range ("one", "two")
  2. res4: scala.collection.immutable.TreeSet[String] = TreeSet(one, three)
  3. scala> res3 from "three"
  4. res5: scala.collection.immutable.TreeSet[String] = TreeSet(three, two)

位集合(Bitset)

位集合是由单字或多字的紧凑位实现的非负整数的集合。其内部使用Long型数组来表示。第一个Long元素表示的范围为0到63,第二个范围为64到127,以此类推(值为0到127的非可变位集合通过直接将值存储到第一个或第两个Long字段的方式,优化掉了数组处理的消耗)。对于每个Long,如果有相应的值包含于集合中则它对应的位设置为1,否则该位为0。这里遵循的规律是,位集合的大小取决于存储在该集合的最大整数的值的大小。假如N是为集合所要表示的最大整数,则集合的大小就是N/64个长整形字,或者N/8个字节,再加上少量额外的状态信息字节。

因此当位集合包含的元素值都比较小时,它比其他的集合类型更紧凑。位集合的另一个优点是它的contains方法(成员测试)、+=运算(添加元素)、-=运算(删除元素)都非常的高效


原文地址:http://docs.scala-lang.org/zh-cn/overviews/collections/sets

0 0