在Scala中添加不可变集合时幕后发生了什么?

时间:2018-01-26 03:59:47

标签: scala immutability

在Scala中工作,我遇到了不可变项,对于此示例immutable.Map。有些时候我无法控制的代码(Spark)会返回我想要处理的immutable.Map并添加元素。我使用以下方法,因为它编译并运行。我希望计算机足够聪明,能够有效地做到这一点,但不要相信我应该做出这样的假设。

var map: immutable.Map[Int, Double] = getMapFromSomewhere()
var i = 0
while(i < 5){
    map += (i -> 0.0)
    i +=1
}

我希望这会占用我的新地图项目,将其放入内存并且不会制作Map的副本,必须通过垃圾回收来清理它。我应该从mutable.Map创建immutable.Map来执行这些类型的操作吗?

2 个答案:

答案 0 :(得分:3)

当您“添加”到不可变集合时,您实际上正在创建一个新集合,理想情况下,它通常与旧集合共享相同的内存和数据。这是安全的,因为收集是不可变的,你不必担心一个中的更改会破坏另一个。

你的代码......不太好。对于Scala来说,这是一种非常丑陋的风格,你的类型已经过时了。 (没有“immutable.Map [Double]”这样的东西,因为Map有两个类型参数。我猜你正在构建一个immutable.Map[Int,Double]。)

这是一种不那么难看的方式来构建你想要构建的东西:

(0 until 5).map( i => (i, 0.0) ).toMap

或者更确切地说,因为您可能以非空地图开始

getMapFromSomwhere() ++ (0 until 5).map(i =>(i, 0.0))

为您真正需要它们的特殊情况保留可变数据结构,并且只有在您仔细考虑过如何管理任何并发或者您可以保证不会有并发访问时才使用它们。 Scala中的默认值应该是以函数样式构建和操作的不可变数据结构,从而避免在示例中对排序进行显式外部迭代。您应该很少使用关键字“var”,例如可变数据结构,仅适用于您仔细考虑过的特殊情况。

答案 1 :(得分:1)

函数式编程语言中的数据结构不仅仅是不可变的(它们的引用一旦创建就不能改变),而且也是持久的。通过持久性方式,它可以重用现有集合来执行某些操作。例如,在Scala之前,优化了一个元素到列表中(所以当你使用list时,你应该认为追加操作是将元素推送到堆栈中。)

同样,其他集合也针对其他操作进行了优化。 我给了你一些参考资料,帮助你更好地理解函数式编程中的持久数据结构。

  1. Persistent data structures in Scala 2。https://www.packtpub.com/mapt/book/application_development/9781783985845/3/ch03lvl1sec25/persistent-data-structures
  2. https://www.youtube.com/watch?v=pNhBQJN44YQ
  3. https://www.youtube.com/watch?v=T0yzrZL1py0