2015-10-15 56 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的麻煩,儘管數據結構本身是不可變的 –