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

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

提问人:newbie 提问时间:12/30/2020 更新时间:12/30/2020 访问量:61

问:

我在理解 Scala 编程第 3 版书中的清单 3.5 中的不可变集和可变集时遇到了一些困惑。该段落告诉我它正在创建不可变的集合,然后用 += 更新它,但随后新存储的集合包含所有三个元素。一些问题:

  • 这与拥有可变集有何不同?不确定我是否看到了区别。
  • 重新分配之前存在的旧集会发生什么情况?
  • 如果可以将新集合重新分配给变量,为什么还要称其为不可变集合呢?jetSet
  • 有人在拖钓我并更改了 PDF 中的“可变”和“不可变”吗?(别担心,我也买了一本即将到货的书。

从书中:

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

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

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

若要将新元素添加到集合中,请在集合上调用 +,传入新元素。在可变集和不可变集上,+ 方法将创建并返回一个添加了元素的新集。在清单 3.5 中,您正在使用一个不可变的集合。尽管可变集合提供了实际的 += 方法,但不可变集合则不然。

在本例中,第二行代码“jetSet += ”Lear“”实质上是以下代码的简写:

jetSet = jetSet + "Lear"

因此,在清单 3.5 的第二行中,您将 jetSet var 重新分配为一个新集合 包含“波音”、“空客”和“李尔”。最后,清单 3.5 的最后一行打印出集合是否包含字符串 “Cessna”。(如您所料,它打印为假。

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

import scala.collection.mutable

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

提前致谢!

斯卡拉 不变性 可变

评论

0赞 Luis Miguel Mejía Suárez 12/30/2020
请注意,正如 jwvh 所说,您通常会避免可变性。当您需要它时(无论出于何种原因),了解不可变集合 + 与可变集合之间的权衡非常重要。您可以在 Internet 上找到更多信息,但 TL;博士;是 5he 可变集合会更快但更危险,因为你不应该泄露它。var

答:

3赞 jwvh 12/30/2020 #1

jetSet是一个 .它在分配后引用了一个新的和不同的。varSet+=

重新分配之前存在的旧集会发生什么情况?

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

movieSet是一个 .它将始终引用相同的内容,即使这会改变其值。valSetSet

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

评论

0赞 newbie 12/30/2020
啊,谢谢。错过了他们之前提到的 var/val 差异。因此,在具有不可变集合的 var 情况下,这在空间和时间方面一定是相当低效的,对吧?新集合的 O(N) 空间加上新元素的大小 + O(N) 复制新集合加上添加新元素的时间?
3赞 Jörg W Mittag 12/30/2020
@newbie:Scala 的大多数不可变数据结构不是“只是”不可变数据结构,它们是持久的不可变数据结构,这意味着它们为“假突变”提供了“高效”的操作。例如,在不可变列表中添加新元素是 O(1) 时间和 O(1) 空间,因为它可以重用现有列表。对于集合也是如此,我相信这些集合在内部实现为 HAMT、Bagwell 尝试或类似的东西,这将使添加一个新元素 O(log n),更具体地说是 O(log n) 具有微小常数。