scala的可变和不可变集何时使用val和var

myt*_*mer 7 scala

我正在阅读Scala Creator编写的Scala编程书,我对Set的例子有点困惑.

这里是不可变集:

var jetSet = Set("Boeing", "Airbus")
jetSet += "Lear"
println(jetSet.contains("Cessna"))
Run Code Online (Sandbox Code Playgroud)

这有什么意义?

该集是不可变的,但变量jetSet是可变的.1)所以每次我用+ =添加到集合中它会创建一个新集合?那么变量指向内存中的新集合?

2)不应该是: val jetSet = set("cow","sheep","duck") ?为什么它必须是var?是否有理由将var用于不可变集合?

Kip*_*ros 16

不可变数据结构(在本例中为Set)的优点是它们是持久的.例如:

var jetSet1 = Set("Boeing", "Airbus")
val jetSet2 = jetSet1 // ... imagine jetSet2 is somewhere else in the program
jetSet1 += "Lear"
assert(!jetSet2.contains("Lear"))
Run Code Online (Sandbox Code Playgroud)

这些Set对象的不变性使得更容易推理程序,因为对jetSet1变量的更新在代码的其他部分(在这种情况下,无论在何处jetSet2使用)都没有副作用.虽然从这个例子中不清楚,但有时候在可变var引用中存储不可变值是很方便的.最常见的是,var意志范围有限(例如,功能的本地范围).

不可变数据结构通常具有非常高效的巧妙实现.不幸的是,Scala集合API没有关于性能的详细记录,但我预计大多数操作大致为O(log N)时间.例如,给定一个大的不可变集合s,应该能够有效地构造s + x一个带有额外元素的新集合.当然,s也保留了不变性保证.在内部,s并且s+x将使用某种树数据结构的与共享组件来存储.

您的问题的标题表明您也在寻找有关使用val或的建议var.经验法则是val随时随地使用.如果a var是必要的,那么尽量尽量限制变量的范围.

  • 不是直接在API中,而是**[记录](http://www.scala-lang.org/docu/files/collections-api/collections.html). (2认同)

San*_*rma 6

var允许您重新分配给变量,将其视为Java中的常规变量声明.但是在上面的例子中,即使你重新分配给同一个变量,它总是一个不同的集合,因为你使用的是一个不可变的变量.

该示例的要点是表明即使您尝试"修改"不可变集合,修改也会创建一个新集合,而不是触及原始集合.如果作者使用了val(final在Java中),他将不得不在范围中引入一个变量来保存新的不可变集.我认为var可能用于保持示例简单.