Mutable and Immutable Collections的区别

来源:互联网 发布:c语言创建多个进程 编辑:程序博客网 时间:2024/06/06 19:56

在写scala的时候,常常不太明白Mutable and Immutable Collections的用法和区别。官方文档说得很清楚:

mutablecollection can be updated or extended in place. This means you can change, add, or remove elements of a collection as a side effect. Immutable collections, by contrast, never change. 

但是我们在用的时候很发现这两个并没什么异样。

一、摆例子,抛出疑惑

例子1-1:

object Test1 extends App() {  var map = new scala.collection.mutable.HashMap[Int, String];  map += (1 -> "1");  map += (2 -> "2");  map += (3 -> "3")  map += (4 -> "4");  map += (1 -> "5");  println(map.mkString("\n"));}
结果:

1 -> 52 -> 23 -> 34 -> 4


这里可以看出是没什么问题的,但是如果把第一行改为immutable的HashMap,你会发现结果依旧没有变。(可能顺序有点变化)

例子1-2:

  var map = new scala.collection.immutable.HashMap[Int, String];
结果:

1 -> 52 -> 23 -> 34 -> 4

那么就奇怪了,其实对于这个基础好的码农一眼就知道了原因,所有的的猫腻都在+=这个操作符上,每次+=操作之后都会返回一个新的对象

也就是说这里共产生了6个map新对象。所以最后输出map的时候其实是最新的那个对象,原来的对象并没有变化。

那么问题是否这样呢?

二、深入验证假设。

例子2-1:

object Test1 extends App() {  var map = new scala.collection.mutable.HashMap[Int, String];  map += (1 -> "1");  map += (2 -> "2");  var tem = map;  tem += (1 -> "5");    println(map.mkString(" || "));  println("---------------")  println(tem.mkString(" || "));}
结果:

2 -> 2 || 1 -> 5
---------------
2 -> 2 || 1 -> 5

奇怪的现象又来了,不是说好的+=操作每次都会返回新对象吗?这个试验的结果很明显最后的tem对象 += 的改变仍然会引起map对象的改变。

也就是说 

tem += (1 -> "5");

根本不会引起一个新对象的产生。它们都指向同一个内存空间。fuck,我要砸键盘了!!!!骂人   别急,请看第二个例子


例子2-2:

修改第一行为:

 var map = new scala.collection.immutable.HashMap[Int, String];
结果:

1 -> 1 || 2 -> 2
---------------
1 -> 5 || 2 -> 2

好了,这个倒是符合我们当初的假设,暂时不砸键盘。


三、总结:

相信聪明的人一下子就能看出区别了。scala用心良苦,在+=这个操作符上为我们花了不少功夫。

+=这个操作符,如果操作的对象是可变的,它会自动调用对象的update方法(具体对象看具体操作),相当于更新或者追加的操作。

如果对象是不可变的,它就会返回一个新的对象。

问题扩展:为什么要花费精力弄明白可变与不可变对象的区别?(这个涉及到多线程安全,循环遍历等,具体自己上网查)






0 0
原创粉丝点击