在 Scala 中添加不可变集合时,幕后发生了什么?
What goes on behind the scenes when adding immutable collections in Scala?
在 Scala 中工作时,我遇到过不可变项,例如 immutable.Map
。有时我无法控制的代码 (Spark) returns 和我想要处理的 immutable.Map
以及添加元素。我正在使用以下方法,因为它可以编译和运行。我希望计算机足够聪明,可以高效地执行此操作,但我不认为我应该做出这样的假设。
var map: immutable.Map[Int, Double] = getMapFromSomewhere()
var i = 0
while(i < 5){
map += (i -> 0.0)
i +=1
}
我希望这会获取我的新地图项,将其放入内存中,而不是制作必须通过垃圾收集清理的地图副本。我是否应该从我的 immutable.Map
创建一个 mutable.Map
来代替执行这些类型的操作?
函数式编程语言中的数据结构不仅简单地不可变(它们的引用一旦创建就不能更改)而且是持久的。通过持久意味着它为某些操作重用现有集合。例如,在 Scala 中,将元素添加到列表中是优化的(因此,当您使用列表时,您应该将追加操作视为一种将元素推入堆栈的操作)。
同样,其他集合也针对其他操作进行了优化。
我给了你一些参考资料,可以帮助你更好地理解函数式编程中的持久数据结构。
当您 "add" 一个不可变集合时,您实际上是在创建一个新集合,理想情况下,它通常与旧集合共享相同的内存和数据。这是安全的,因为集合是不可变的,您不必担心其中一个的更改会破坏另一个。
您的代码……不太好。对于 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",例如可变数据结构,仅用于您仔细考虑过的特殊情况。
在 Scala 中工作时,我遇到过不可变项,例如 immutable.Map
。有时我无法控制的代码 (Spark) returns 和我想要处理的 immutable.Map
以及添加元素。我正在使用以下方法,因为它可以编译和运行。我希望计算机足够聪明,可以高效地执行此操作,但我不认为我应该做出这样的假设。
var map: immutable.Map[Int, Double] = getMapFromSomewhere()
var i = 0
while(i < 5){
map += (i -> 0.0)
i +=1
}
我希望这会获取我的新地图项,将其放入内存中,而不是制作必须通过垃圾收集清理的地图副本。我是否应该从我的 immutable.Map
创建一个 mutable.Map
来代替执行这些类型的操作?
函数式编程语言中的数据结构不仅简单地不可变(它们的引用一旦创建就不能更改)而且是持久的。通过持久意味着它为某些操作重用现有集合。例如,在 Scala 中,将元素添加到列表中是优化的(因此,当您使用列表时,您应该将追加操作视为一种将元素推入堆栈的操作)。
同样,其他集合也针对其他操作进行了优化。 我给了你一些参考资料,可以帮助你更好地理解函数式编程中的持久数据结构。
当您 "add" 一个不可变集合时,您实际上是在创建一个新集合,理想情况下,它通常与旧集合共享相同的内存和数据。这是安全的,因为集合是不可变的,您不必担心其中一个的更改会破坏另一个。
您的代码……不太好。对于 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",例如可变数据结构,仅用于您仔细考虑过的特殊情况。