可变和不可变集合的+=操作含义

转载自:http://hongjiang.info/scala-pitfalls-22/

可变和不可变集合的 += 操作含义不同:
       不可变 imSet += newEle 等价于 imSet = imSet + newEle
       可变 mSet += newEle 等价于 mSet.+=(newEle) 是方法而非操作符

举个例子:如下一段代码:
var map = scala.collection.immutable.Map[Int,Int]()
map += (1->2)
map += (3->4)
...
if (xxx) map.get(..)
map这里用的不可变集合,+=方法应该是返回一个新的值,后边的get应该不能生效。另外觉得 += 这个方法似乎应该只在mutable集合下才有。

看一下编译器怎么翻译的:
scala> import reflect.runtime.universe._
import reflect.runtime.universe._

scala> var m = Map[Int,Int]()
m: scala.collection.immutable.Map[Int,Int] = Map()

scala> reify ( m += (1->1) )
res0: reflect.runtime.universe.Expr[Unit] 
             = Expr[Unit]($read.m_$eq($read.m.$plus(Predef.ArrowAssoc(1).$minus$greater(1))))
可以看出,immutable.Map 在var声明下支持 += 操作。但这里+=是赋值操作符而不是方法,在scala下赋值操作符仅对var修饰的变量生效。m += (k->v)相当于 m = m + (k->v) 而Map里正好定义了+方法。如果没有定义过+方法的话,编译器会采用字符串连接,也就是对+前后的对象进行toString然后拼接;这种情况下会因为类型不匹配而报错。

建议还是采用val修饰一个可变的Map,来存放数据。
补充,对于var变量,即使以.+=方式调用,编译器也会对待为操作符:
scala> reify ( m.+=(1->1) )
res1: reflect.runtime.universe.Expr[Unit] 
             = Expr[Unit]($read.m_$eq($read.m.$plus(Predef.ArrowAssoc(1).$minus$greater(1))))

你可能感兴趣的:(Scala)