为什么突变scala.collection.immutable.SortedMap和scala.collection.immutable.TreeMap是可能的
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
+=的定义,那么它是如何存在的呢?
发布于 2016-06-29 11:24:47
我同意语法看起来像是在改变对象,但实际上,+=操作只是对原始对象进行添加(使用+操作符)然后重新赋值(当原始变量是var时)的语法糖。所以:
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)等同于:
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来查看:
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')为了进行比较,请看这个可变映射:
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映射的内容,只有在对象是可变的情况下才能这样做。
发布于 2016-06-29 11:19:13
不可变集合的工作方式是添加、删除或修改元素的操作,而不是在堆上创建新集合。因此,如果有多个变量包含对您的SortedMap的引用,那么除了您修改的那个变量之外,其他变量仍然会引用您的原始集合,而不是修改后的版本。(这一点很重要,因为人们希望从不可变集合中获得的主要好处之一是安全的多线程和并行化。)
请注意,虽然我说的是“创建一个新的集合”,但许多元素可能不需要复制。为了提高效率,它们将在可能的情况下引用堆上的相同对象。这种共享对用户很大程度上是不可见的(除了性能优势),因为一旦您更改了这些共享元素中的一个,两个集合将不再引用相同的元素。Scala的不可变集合通常是这样设计的,这样可以在复制尽可能少的集合的同时完成修改。
还要注意,只有在将sm声明为var而不是val时,才能对sm引用的集合进行这种修改。由于您只是通过返回一个新的集合来“修改”集合,所以存储在变量中的引用必须更改。相反,可以就地修改可变集合,因此在这种情况下,即使sm被声明为val,也可以更改sm引用的集合。
关于sm +=在哪里定义的问题,这是sm = sm +的语法糖。表达式sm + (2 -> 'x')返回对添加此元素所产生的新集合的引用,然后将此引用分配给sm。
https://stackoverflow.com/questions/38089435
复制相似问题