set

20 阅读4分钟

image.png

  1. Set 的本质:无序、不重复的集合(和 Map 的 "键不可重复" 逻辑一致,但没有键值对关系)。
  2. 默认不可变scala.collection.immutable.Set(如果需要修改,需显式使用mutable.Set)。
  3. 自动去重:创建时传入重复元素,会自动过滤,最终只保留唯一元素。
  4. 无序特性:输出的元素顺序可能和创建时的顺序不一致(底层是哈希表实现)
package set

object set01 {
  def main(args: Array[String]): Unit = {
    // 定义一个set
    val set1 = Set("apple", "grape", "apple", "pear")
    println(set1)
  }
}

1. 可变 Set 核心特点

  • 必须显式导入 scala.collection.mutable.Set(不可省略,否则默认是不可变)
  • 支持 +=(添加元素)、-=(删除元素)等直接修改操作
  • 修改时不会创建新对象,而是直接操作原集合的内容

2. 不可变 Set 核心特点

  • 默认无需导入(Scala 自动关联 scala.collection.immutable.Set
  • 不支持 +=-= 直接修改,强行使用会编译报错
  • 只能通过 +(添加元素)、-(删除元素)生成新集合,原集合始终不变
  • 若要保存修改结果,需用变量(var)接收新集合(如代码中的 newCourse

3. 共同特性

  • 无论可变 / 不可变,Set 都具备「自动去重」和「无序」特性
  • 创建时传入重复元素会自动过滤,输出顺序与创建顺序无关
/*
* 可变(mutable),不可变(immutable)
*   可变:自己的内容可以直接修改。可以使用 +=
*   不可变:自己的内容定义好了,就不能添加,不能删除。
* 默认使用的是 不可变的。
* Set 它是内置对象,不需要import,可以直接使用。等价于 import scala.collection.immutable.Set
* */

object set02 {
  def main(args: Array[String]): Unit = {
    // 分: 可变set,不可变
    // 默认情况下,使用的Set就是不可变的。

    // 可变的Set
    val set1 = scala.collection.mutable.Set("apple", "grape", "apple", "pear")
    set1 += "banana"

    println(set1)

    // 不可变的Set
    val course = scala.collection.immutable.Set("apple", "banana")
    // 报错: course += "xxxx"
    var newCourse = course + "pear"
    println(newCourse)
  }
}

可变 / 不可变 Set 的操作差异

  • 可变 Set(mutable.Set):支持 +=(添加)、-=(删除),直接修改原集合;
  • 不可变 Set(immutable.Set):不支持 +=/-=,需用 +(添加)、-(删除)生成新集合(原集合不变)
package Level02

object src {
  /*
   * Set的操作
   * 1. 添加元素
   * 2. 删除元素
   * 3. 查询元素是否存在
   * 4. 合并Set
   * 5. 交集
   * 6. 差集
   */
  object set03 {
    def main(args: Array[String]): Unit = {
      // 可变的Set
      val set1 = scala.collection.mutable.Set("apple", "grape", "apple", "pear")
      // 1. 添加元素
      set1 += "banana"

      // 2. 删除元素 grape
      set1 -= "grape"

      //3. 查询元素是否存在 contains 它返回一个Bool值
      if (set1.contains("apple")) {
        println("apple 存在")
      }

      // 4. 合并Set union 返回一个新的Set
      val set2 = scala.collection.mutable.Set("orange")
      val set3 = set1.union(set2)
      println(set3)

      //5.交集
      val hobby1=scala.collection.mutable.Set("看书","听歌")
      val hobby2=scala.collection.mutable.Set("打球","看书")

      //求交集
      val rst = hobby1.intersect(hobby2)
      println(rst)

      //6.差集:一个Set中有,而另一个没有。
      val classes1=scala.collection.immutable.Set("语文","数学","英语")
      val classes2=scala.collection.immutable.Set("语文","物理")
      val rst1=classes2.diff(classes1)
      println(rst1)
    }
  }

}

核心区别总结

特性可变 Map(mutable.Map不可变 Map(immutable.Map
修改方式直接修改原集合(+=/-= 等)不修改原集合,返回新集合(+/-
线程安全不安全(多线程修改可能出问题)安全(不可变对象天然线程安全)
性能频繁修改时性能好(无新对象创建)读取 / 少量修改时性能好(内部优化)
推荐使用场景单线程、需要频繁增删改键值对多线程环境、数据稳定(读多写少)
package Level02

/*
 * Map, 映射,表示一种一一对应关系!
 */
object src1 {
  def main(args: Array[String]): Unit = {
    // 创建可变的Map 键 值 对
    val scores = scala.collection.mutable.Map("alice" -> 90, "bob" -> 85)
    // 添加
    scores += ("max" -> 100)

    println(scores)

    // 创建不可变的Map
    val provinceInfo = scala.collection.immutable.Map("42" -> "湖北")
    // provinceInfo += ("14" -> "山西")
    val newInfo = provinceInfo + ("14" -> "山西")
    println(newInfo)
  }
}
package Level02
object src2 {
  def main(args: Array[String]): Unit = {
    // 创建可变的Map 键 值 对
    val scores = scala.collection.mutable.Map("alice" -> 90, "bob1" -> 85)
    // 1. 添加
    scores += ("max" -> 100)

    // 2. 删除 alice。删除操作是根据key来做的
    scores -= "alice"

    // 3. 查询。查看bob的分数. rst 是一个option类型
    val rst = scores.get("bob1")
    if(rst.isEmpty){
      println("bobi没有成绩")
    } else {
      println(rst.get)
    }

    // 4. 遍历
    println(scores)
    // for
    for((key,value) <- scores){
      println(s"${key}, ${value}")
    }

    // foreach
    scores.foreach{
      case (key,value) => println(s"${key}, ${value}")
    }
  }
}