首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么突变immutable.SortedMap和immutable.TreeMap是可能的?

为什么突变immutable.SortedMap和immutable.TreeMap是可能的?
EN

Stack Overflow用户
提问于 2016-06-29 10:37:53
回答 2查看 249关注 0票数 2

为什么突变scala.collection.immutable.SortedMapscala.collection.immutable.TreeMap是可能的

代码语言:javascript
复制
scala> import scala.collection.immutable.SortedMap
import scala.collection.immutable.SortedMap

scala> var sm = SortedMap(3 -> 'x', 1 -> 'x', 4 -> 'x')
sm: scala.collection.immutable.SortedMap[Int,Char] = Map(1 -> x, 3 -> x, 4 -> x)

scala> sm += (2 -> 'x')

scala> sm
res1: scala.collection.immutable.SortedMap[Int,Char] = Map(1 -> x, 2 -> x, 3 -> x, 4 -> x)

另外,我不认为在

http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.SortedMap

http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.TreeMap

+=的定义,那么它是如何存在的呢?

EN

回答 2

Stack Overflow用户

发布于 2016-06-29 11:24:47

我同意语法看起来像是在改变对象,但实际上,+=操作只是对原始对象进行添加(使用+操作符)然后重新赋值(当原始变量是var时)的语法糖。所以:

代码语言:javascript
复制
scala> import scala.collection.immutable.SortedMap
import scala.collection.immutable.SortedMap

scala> var sm = SortedMap(3 -> 'x', 1 -> 'x', 4 -> 'x')
sm: scala.collection.immutable.SortedMap[Int,Char] = Map(1 -> x, 3 -> x, 4 -> x)

scala> sm += (2 -> 'x')

scala> sm
res1: scala.collection.immutable.SortedMap[Int,Char] = Map(1 -> x, 2 -> x, 3 -> x, 4 -> x)

等同于:

代码语言:javascript
复制
scala> var sm2 = SortedMap(3 -> 'x', 1 -> 'x', 4 -> 'x')
sm2: scala.collection.immutable.SortedMap[Int,Char] = Map(1 -> x, 3 -> x, 4 -> x)

scala> sm2 = sm2 + (2 -> 'x')
sm2: scala.collection.immutable.SortedMap[Int,Char] = Map(1 -> x, 2 -> x, 3 -> x, 4 -> x)

可以通过尝试使用val来查看:

代码语言:javascript
复制
scala> val sm3 = SortedMap(3 -> 'x', 1 -> 'x', 4 -> 'x')
sm3: scala.collection.immutable.SortedMap[Int,Char] = Map(1 -> x, 3 -> x, 4 -> x)

scala> sm3 += (2 -> 'x')
<console>:10: error: value += is not a member of scala.collection.immutable.SortedMap[Int,Char]
              sm3 += (2 -> 'x')

为了进行比较,请看这个可变映射:

代码语言:javascript
复制
scala> val sm4 = scala.collection.mutable.Map[Int, Char](1 -> 'x')
sm4: scala.collection.mutable.Map[Int,Char] = Map(1 -> x)


scala> sm4.put(2, 'x')
res6: Option[Char] = None

scala> sm4
res7: scala.collection.mutable.Map[Int,Char] = Map(2 -> x, 1 -> x)

在这里,我们能够更改val映射的内容,只有在对象是可变的情况下才能这样做。

票数 6
EN

Stack Overflow用户

发布于 2016-06-29 11:19:13

不可变集合的工作方式是添加、删除或修改元素的操作,而不是在堆上创建新集合。因此,如果有多个变量包含对您的SortedMap的引用,那么除了您修改的那个变量之外,其他变量仍然会引用您的原始集合,而不是修改后的版本。(这一点很重要,因为人们希望从不可变集合中获得的主要好处之一是安全的多线程和并行化。)

请注意,虽然我说的是“创建一个新的集合”,但许多元素可能不需要复制。为了提高效率,它们将在可能的情况下引用堆上的相同对象。这种共享对用户很大程度上是不可见的(除了性能优势),因为一旦您更改了这些共享元素中的一个,两个集合将不再引用相同的元素。Scala的不可变集合通常是这样设计的,这样可以在复制尽可能少的集合的同时完成修改。

还要注意,只有在将sm声明为var而不是val时,才能对sm引用的集合进行这种修改。由于您只是通过返回一个新的集合来“修改”集合,所以存储在变量中的引用必须更改。相反,可以就地修改可变集合,因此在这种情况下,即使sm被声明为val,也可以更改sm引用的集合。

关于sm +=在哪里定义的问题,这是sm = sm +的语法糖。表达式sm + (2 -> 'x')返回对添加此元素所产生的新集合的引用,然后将此引用分配给sm

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38089435

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档