2015-10-15 54 views
2

我很有兴趣了解以最有效的方式修改不可变集合的模式。修改不可变集合的习惯性方法

假设例如我要定义下面的类(实际的实现可能超载运营商,但是这仅仅是为了说明)。这是最好的方式(关于性能/安全性)?

import scala.collection.immutable.HashMap 
class Example[A,B] { 
    var col = new HashMap[A, B]() 
    def add(k: A, v: B): Unit = col = col + (k -> v) 
    def remove(k: A): Unit = col = col - k 
} 

这种方法是否可能,以某种方式,我错过了?

class Example[A,B] extends HashMap[A,B] { 
    def add(k: A, v: B): Unit = ??? 
    def remove(k: A): Unit = ??? 
} 
+2

我知道我可能听起来很明显,但最有效的方法是不使用不可变集合:在这种情况下,使用可变映射 –

+2

om-nom-nom是正确的私有val会更好。一旦你使用了'var',你已经引入了不变性。通过将'var'的类型作为一个不可变的集合,你并不清楚。 – Owen

+0

@ om-nom-nom我明白了,这种情况下的变种是必要的,以使这种方法的工作。不要声称这是做这件事的最好方式。问题的关键是以一种惯用的方式向专家询问更好的方法。 –

回答

1

这听起来像你试图让不可变的数据结构可变。在某些情况下,您需要考虑性能,但是鉴于Scala具有持久的数据结构,我将重点放在用例上,而不是性能模型。

val a = Map("key1" -> "some value") 
val b = a + ("key2" -> "some other value") 

现在b包含两个条目。

如果你真的需要为你的情况可变的结构,只需使用mutable.Map

+0

谢谢。用例是小型收集器(最多200个项目),我需要非常快速的读取访问权限。写入不是很常见,并且可能每5秒发生一次......我需要以线程安全的方式支持GetOrElseAdd()模式。 –

2

上述评论是正确的。不可变的数据结构的想法存在,并且有办法做到这一点,然而,看起来你可能只想坚持使用可变结构,因为无论如何你都有一个var

查看免费的Scala编程的在线pdf第17章here其中Odersky讨论了设计和构建Immutable队列。

它的要点是,你永远不会修改你想要改变的结构,你只要把它放在里面,看看它,然后建立一个基于旧的结构的新结构,不管它是什么正在努力去做。

这是事实背后同样的想法,与列表:

val list = List(1,2,3) 
1 :: list 
println(list) 

会打印出List(1,2,3)而不是List(1,1,2,3)

虽然:

val list = List(1,2,3) 
val list1 = 1 :: list 
println(list1) 

是什么打印List(1,1,2,3)

这是一个不错的选择讨论一些流行的数据结构及其功能对应的知识库。 Functional Data Structures

+0

谢谢。var只是一种让特定方法起作用的方法,如果可以的话,我会摆脱它。 如果我将我的代码移动到一个可变集合中,我必须在并发线程中混合使它成为线程安全的。从性能角度来看,如果我大部分都是读取,那么可能是正确的?给定100-200个项目的小集合,偶尔(每分钟10-20个)更新,哪个最适合? 无论如何,我的问题主要是学术问题,以更好地理解Scala。感谢您的PDF链接,我会做一些阅读。 –

+0

@WillIAm万一你的代码是并发的,你可能会遇到var的麻烦,尽管数据结构本身是不可变的 –