4.2 Scala集合:Set

Set 是一个不重复元素的无序集合。它不包含重复元素。此外,它不允许通过索引访问一个元素,因为它并没有索引。

下面是一个Set 的例子:

val fruits = Set("apple", "orange", "pear", "banana")
val set1 = Set(1,2,3,2,3,4,5,5)

Sets 支持两个基本操作:

  • contains:如果set 包含输入参数,则返回true;

  • isEmpty:如果set 是空的,返回true;

Set是不重复元素的集合。尝试将已有元素加入进来是没有效果的。比如:

(Set(2,0,1) + 1).foreach(println)

【示例】学习如何使用Scala的不可变Set集合,并执行一些常见的操作,如初始化,添加元素,添加集合,集合的差集和交集,以及创建空集合。

/**
* Set是一种数据结构,它允许存储一些值,但这些值不能重复。
*/
object SetDemo {
def main(args: Array[String]): Unit = {
  println("1: 初始化一个有3个元素的集合")
  val set1: Set[String] = Set("苹果","香蕉","葡萄干","苹果")
  println(s"set1的元素 = $set1")

  println("\n2: 检查集合中存在的特定元素")
  println(s"是否有苹果 = ${set1("苹果")}")
  println(s"是否有香蕉 = ${set1("香蕉")}")
  println(s"是否有葡萄干 = ${set1("葡萄干")}")
  println(s"是否有火龙果 = ${set1("火龙果")}")

  println("\n3: 使用+ 在Set 中添加元素")
  val set2: Set[String] = set1 + "火龙果" + "葡萄干"
  println(s"使用 + 向Set集合中添加元素 = $set2")

  println("\n4: 使用 ++ 将两个Set集合添加到一起")
  val set3: Set[String] = set1 ++ Set[String]("火龙果", "葡萄干")
  println(s"使用 ++ 将两个Set集合添加到一起 = $set3")

  println("\n5: 使用 - 从Set 中删除元素")
  val set4: Set[String] = set1 - "苹果"
  println(s"去掉苹果后的Set集合元素 = $set4")

  println("\n6: 使用& 找到两个集合之间的交集")
  val set5: Set[String] = Set("火龙果", "香蕉", "苹果")
  println(s"set1和set5的交集 = ${set1 & set5}")

  println("\n7: 使用 &~ 找出两个集合的差集")
  println(s"set1和set5的差集 = ${set1 &~ set5}")

  println("\n8: 初始化一个空集")
  val emptySet: Set[String] = Set.empty[String]
  println(s"Empty Set = $emptySet")
}
}

Set是一种数据结构,它允许存储一些值,但这些值不能重复。Set不保留元素插入的顺序。默认情况下,Set是以HashSet实现的,其元素根据hashCode方法的值进行组织。

Set(1,2,3,5,7,8).foreach(println)

【示例】下面是使用HashSet的示例。

在Scala中,HashSet是Set语义的具体实现。HashSet将使用元素的hashCode作为键,以便在HashSet中快速查找元素的值。学习如何使用Scala的不可变HashSet,并执行一些常见的操作,如初始化、添加元素、添加HashSet、HashSet差集和交集、以及创建空HashSet。

Scala中HashSet的内部数据结构是一个HashTrie,如果你有Java背景,会发现这与Java中的HashTable是不同的。

import scala.collection.immutable.HashSet

object HashSetDemo {
def main(args: Array[String]): Unit = {
  println("1: 初始化一个有3个元素的集合")
  val hashSet1: HashSet[String] = HashSet("苹果","香蕉","葡萄干","苹果")
  println(s"hashSet1的元素 = $hashSet1")

  println("\n2: 检查集合中存在的特定元素")
  println(s"是否有苹果 = ${hashSet1("苹果")}")
  println(s"是否有香蕉 = ${hashSet1("香蕉")}")
  println(s"是否有葡萄干 = ${hashSet1("葡萄干")}")
  println(s"是否有火龙果 = ${hashSet1("火龙果")}")

  println("\n3: 使用+ 在HashSet 中添加元素")
  val hashSet2: HashSet[String] = hashSet1 + "火龙果" + "葡萄干"
  println(s"使用 + 向Set集合中添加元素 = $hashSet2")

  println("\n4: 使用 ++ 将两个Set集合添加到一起")
  val hashSet3: HashSet[String] = hashSet1 ++ HashSet[String]("火龙果", "葡萄干")
  println(s"使用 ++ 将两个Set集合添加到一起 = $hashSet3")

  println("\n5: 使用 - 从Set 中删除元素")
  val hashSet4: HashSet[String] = hashSet1 - "苹果"
  println(s"去掉苹果后的Set集合元素 = $hashSet4")

  println("\n6: 使用& 找到两个集合之间的交集")
  val hashSet5: HashSet[String] = HashSet("火龙果", "香蕉", "苹果")
  println(s"set1和set5的交集 = ${hashSet1 & hashSet5}")

  println("\n7: 使用 &~ 找出两个集合的差集")
  println(s"hashSet1和hashSet5的差集 = ${hashSet1 &~ hashSet5}")

  println("\n8: 初始化一个空集")
  val emptyHashSet: HashSet[String] = HashSet.empty[String]
  println(s"Empty Set = $emptyHashSet")
}
}

LinkedHashSet可以记住元素被插入的顺序。它会维护一个链表来达到这个目的。

val weeks= scala.collection.mutable.LinkedHashSet("Mo","Tu","We","Th","Fr")
weeks.foreach(println)

继之前关于HashSet和Set的之后,TreeSet允许存储惟一的元素,但也提供了元素的排序。根据Scala文档,TreeSet内部使用了一个Red-Back数据结构来确保一个平衡的树,为大多数操作提供O(log n)。

【示例】学习如何使用Scala的不可变TreeSet,并执行一些常见的操作,如初始化、添加元素、添加TreeSet、TreeSet差集和交集、排序、创建空的TreeSet。

import scala.collection.immutable.TreeSet

/**
* 由于正在处理Set语义,因此只存储唯一的和不可重复的值。
*/
object TreeSetDemo {
def main(args: Array[String]): Unit = {
  println("1: 初始化一个有3个元素的集合")
  val treeSet1: TreeSet[String] = TreeSet("苹果","香蕉","葡萄干","苹果")
  println(s"treeSet1的元素 = $treeSet1")

  println("\n2: 检查集合中存在的特定元素")
  println(s"是否有苹果 = ${treeSet1("苹果")}")
  println(s"是否有香蕉 = ${treeSet1("香蕉")}")
  println(s"是否有葡萄干 = ${treeSet1("葡萄干")}")
  println(s"是否有火龙果 = ${treeSet1("火龙果")}")

  println("\n3: 使用+ 在TreeSet 中添加元素")
  val treeSet2: TreeSet[String] = treeSet1 + "火龙果" + "葡萄干"
  println(s"使用 + 向TreeSet集合中添加元素 = $treeSet2")

  println("\n4: 使用 ++ 将两个Set集合添加到一起")
  val treeSet3: TreeSet[String] = treeSet1 ++ TreeSet[String]("火龙果", "葡萄干")
  println(s"使用 ++ 将两个TreeSet集合添加到一起 = $treeSet3")

  println("\n5: 使用 - 从TreeSet 中删除元素")
  val treeSet4: TreeSet[String] = treeSet1 - "苹果"
  println(s"去掉苹果后的Set集合元素 = $treeSet4")

  println("\n6: 使用& 找到两个集合之间的交集")
  val treeSet5: TreeSet[String] = TreeSet("火龙果", "香蕉", "苹果")
  println(s"treeSet1和treeSet5的交集 = ${treeSet1 & treeSet5}")

  println("\n7: 使用 &~ 找出两个集合的差集")
  println(s"treeSet1和treeSet5的差集 = ${treeSet1 &~ treeSet5}")

  println("\n8: 改变TreeSet的顺序为降序字母排列")
  object AlphabetOrdering extends Ordering[String] {
    def compare(element1:String, element2:String): Int = element2.compareTo(element1)
  }
  val treeSet6: TreeSet[String] = TreeSet("苹果","香蕉","葡萄干")(AlphabetOrdering)
  println(s"treeSet6的元素 = $treeSet6")

  println("\n9: 初始化一个空集")
  val emptyTreeSet: TreeSet[String] = TreeSet.empty[String]
  println(s"Empty TreeSet = $emptyTreeSet")
}
}

如果想要按照已排序的顺序来访问其中的元素,使用SortedSet:

scala.collection.immutable.SortedSet(1,2,3,4,5,6).foreach(println)

继前面关于Set、HashSet和TreeSet之后,SortedSet允许存储惟一的元素,但也提供了元素的排序。根据Scala文档,SortedSet是一种特征(trait)。它的具体类实现是讨论过的TreeSet。

【示例】学习如何使用Scala的不可变SortedSet,并执行一些常见的操作,如初始化、添加元素、添加SortedSet、SortedSet的差集和交集、排序和创建空的SortedSet。

import scala.collection.immutable.SortedSet

object SortedSetDemo {
def main(args: Array[String]): Unit = {
  println("1: 初始化一个有3个元素的集合")
  val sortedSet1: SortedSet[String] = SortedSet("苹果","香蕉","葡萄干","苹果")
  println(s"sortedSet1的元素 = $sortedSet1")

  println("\n2: 检查集合中存在的特定元素")
  println(s"是否有苹果 = ${sortedSet1("苹果")}")
  println(s"是否有香蕉 = ${sortedSet1("香蕉")}")
  println(s"是否有葡萄干 = ${sortedSet1("葡萄干")}")
  println(s"是否有火龙果 = ${sortedSet1("火龙果")}")

  println("\n3: 使用+ 在TreeSet 中添加元素")
  val sortedSet2: SortedSet[String] = sortedSet1 + "火龙果" + "葡萄干"
  println(s"使用 + 向SortedSet集合中添加元素 = $sortedSet2")

  println("\n4: 使用 ++ 将两个Set集合添加到一起")
  val sortedSet3: SortedSet[String] = sortedSet1 ++ SortedSet[String]("火龙果", "葡萄干")
  println(s"使用 ++ 将两个SortedSet集合添加到一起 = $sortedSet3")

  println("\n5: 使用 - 从SortedSet中删除元素")
  val sortedSet4: SortedSet[String] = sortedSet1 - "苹果"
  println(s"去掉苹果后的SortedSet集合元素 = $sortedSet4")

  println("\n6: 使用& 找到两个集合之间的交集")
  val sortedSet5: SortedSet[String] = SortedSet("火龙果", "香蕉", "苹果")
  println(s"sortedSet1和sortedSet5的交集 = ${sortedSet1 & sortedSet5}")

  println("\n7: 使用 &~ 找出两个集合的差集")
  println(s"sortedSet1和sortedSet5的差集 = ${sortedSet1 &~ sortedSet5}")

  println("\n8: 改变SortedSet的顺序为降序字母排列")
  object AlphabetOrdering extends Ordering[String] {
    def compare(element1:String, element2:String): Int = element2.compareTo(element1)
  }
  val sortedSet6: SortedSet[String] = SortedSet("苹果","香蕉","葡萄干")(AlphabetOrdering)
  println(s"sortedSet6的元素 = $sortedSet6")

  println("\n9: 初始化一个空集")
  val emptySortedSet: SortedSet[String] = SortedSet.empty[String]
  println(s"Empty TreeSet = $emptySortedSet")
}
}

即可保证顺序,又要保证唯一性,可以使用ListSet类型。

【示例】使用不可变的ListSet。

import scala.collection.immutable.ListSet

object ListSetDemo {
def main(args: Array[String]): Unit = {
println("1:初始化一个不可变的ListSet")
// val listSet1: ListSet[String] = ListSet("苹果","香蕉","葡萄干")
val listSet1 = ListSet("苹果","香蕉","葡萄干") // 使用类型推断
println(s"listSet1的元素有 = $listSet1")

println("\n2: 检查不可变ListSet的元素")
println(s"Element 苹果 = ${listSet1("苹果")}")
println(s"Element 香蕉 = ${listSet1("香蕉")}")
println(s"Element 葡萄干 = ${listSet1("葡萄干")}")
println(s"Element 草莓 = ${listSet1("草莓")}")

println("\n3: ListSet是一个递归数据结构")
println(s"head of listset is = ${listSet1.head}")
println(s"tail of listset is = ${listSet1.tail}")
println(s"tail of listset is = ${listSet1.tail.head}")
println(s"tail of listset is = ${listSet1.tail.tail}")

println("\n4: 使用+ 向不可变的ListSet添加元素")
// val listSet2: ListSet[String] = listSet1 + "草莓"
val listSet2: ListSet[String] = listSet1 + "葡萄干"
println(s"在ListSet中添加元素,使用 + = $listSet2")

println("\n5: 使用 ++ 将两个ListSet添加到一起")
val listSet3: ListSet[String] = listSet1 ++ ListSet("火龙果","苹果")
println(s"添加两个列表一起,使用 ++ = $listSet3")

println("\n6: 从ListSet删除元素,使用 -")
val listSet4: ListSet[String] = listSet1 - "苹果"
println(s"没有苹果元素的ListSet = $listSet4")

println("\n7: 初始化一个空的ListSet")
val emptyListSet: ListSet[String] = ListSet.empty[String]
println(s"String类型的空ListSet = $emptyListSet")
}
}

什么是BitSet?

继之前的Set、HashSet、TreeSet和SortedSet之后,BitSet也允许存储没有可重复值的唯一元素。根据Scala文档,BitSet表示一个小整数的集合,作为一个大整数的位。在本例中,我们将重点关注BitSet的set语义。

【示例】学习如何使用Scala的不可变BitSet,并执行一些常见的操作,如初始化,添加元素,添加BitSet, BitSet差集和交集,以及创建空BitSet。

import scala.collection.immutable.BitSet

object BitSetDemo {
def main(args: Array[String]): Unit = {
  println("1: 初始化一个具有3个元素的BitSet")
  val bitSet1: BitSet = BitSet(3, 2, 0)
  println(s"bitSet1中的元素 = $bitSet1")

  println("\n2: 在BitSet中检查特定的元素")
  println(s"Element 0 = ${bitSet1(0)}")
  println(s"Element 2 = ${bitSet1(2)}")
  println(s"Element 3 = ${bitSet1(3)}")
  println(s"Element 3 = ${bitSet1(1)}")

  println("\n3: 使用 + 在BitSet中添加元素")
  val bitSet2: BitSet = bitSet1 + 13 + 13
  println(s"使用 + 在BitSet中添加元素 = $bitSet2")

  println("\n4: 使用++ 将两个BitSet添加到一起")
  val bitSet3: BitSet = bitSet1 ++ BitSet(13, 14, 15, 16, 17)
  println(s"使用++ 将两个BitSet添加到一起 = $bitSet3")

  println("\n5: 使用- 在BitSet中删除元素")
  val bitSet4: BitSet = bitSet1 - 0
  println(s"移除元素0后的BitSet = $bitSet4")

  println("\n6: 使用& 找到两个BitSet之间的交集")
  val bitSet5: BitSet = BitSet(0, 2, 4)
  println(s"bitSet1和bitSet5的交集 = ${bitSet1 & bitSet5}")

  println("\n7:使用 &~ 找到两个BitSet之间的差集")
  println(s"bitSet1和bitSet5的差集 = ${bitSet1 &~ bitSet5}")

  println("\n8: 初始化一个空的 BitSet")
  val emptyBitSet: BitSet = BitSet.empty
  println(s"Empty BitSet = $emptyBitSet")
}
}
© 版权声明
THE END
喜欢就支持一下吧
点赞189赞赏 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

夸夸
夸夸
还有吗!没看够!
取消
昵称表情代码图片

    暂无评论内容