Scala 编程示例混淆(清单 3.5,创建可变和不可变集)

Programming in Scala example confusion (Listing 3.5, creating mutable and immutable sets)

我对《Programming in Scala》第 3 版中清单 3.5 中的不可变集和可变集的理解有些困惑。该段落告诉我它正在创建不可变集,然后用 += 更新它,但是新存储的集包含所有三个元素。一些问题:

摘自本书:

创建集合的默认方式如清单 3.5 所示:

var jetSet = Set("Boeing", "Airbus") 
jetSet += "Lear" 
println(jetSet.contains("Cessna"))

清单 3.5 - 创建、初始化和使用不可变集。 图 3.2 - Class Scala 集合的层次结构(不包括在内)。 在代码清单 3.5 的第一行代码中,您定义了一个名为 jetSet 的新变量,并使用包含两个字符串“Boeing”和“Airbus”的不可变集对其进行了初始化。如本示例所示,您可以在 Scala 中创建集合,方法与创建列表和数组的方式类似:通过在 Set 伴生对象上调用名为 apply 的工厂方法。在清单 3.5 中,您在 scala.collection.immutable.Set 的伴生对象上调用 apply,它 return 是一个默认的、不可变的 Set 的实例。 Scala 编译器将 jetSet 的类型推断为不可变的 Set[String].

要向集合中添加新元素,您可以在集合上调用 + 并传入新元素。在可变集和不可变集上,+ 方法将创建并 return 一个添加了元素的新集。在清单 3.5 中,您使用的是一个不可变集。尽管可变集提供了实际的 += 方法,但不可变集却没有。

在这种情况下,第二行代码“jetSet += "Lear"”本质上是 shorthand 用于:

jetSet = jetSet + "Lear"

因此,在清单 3.5 的第二行中,您使用新的集合重新分配了 jetSet 变量 包含“Boeing”、“Airbus”和“Lear”。最后,清单 3.5 的最后一行打印出该集合是否包含字符串“Cessna”。 (如您所料,它打印出错误。)

如果你想要一个可变集,你需要使用导入,如清单 3.6 所示:

import scala.collection.mutable

val movieSet = mutable.Set("Hitch", "Poltergeist") 
movieSet += "Shrek"
println(movieSet)

提前致谢!

jetSet 是一个 var。它在 += 赋值之后引用了一个新的和不同的 Set

What happens to the old set that is existed before reassignment?

如果前面的 2 元素 Set 没有被任何其他变量引用,那么它将被垃圾收集掉。

movieSet 是一个 val。它总是引用相同的 Set,即使 Set 改变了它的值。

突变通常被认为是不可取的,有经验的 Scala 编码人员会避免这两种情况。