2016-12-25 78 views
0

收藏我只是模擬的API在內存假的數據庫,並使用scala.collection.mutable.HashMap[Int, AnyRef]關於斯卡拉

  1. 即支持併發插入的最佳採集簡單的問題?有更好的選擇?

  2. 假設我需要另一種類似的集合,如Map[Int, AnyRef],但這次鍵需要排序。 TreeMap是最佳選擇嗎?

在此先感謝

回答

0

你有兩個選擇這裏。

您可以使用不可變的數據結構,如scala.collection.immutable.HashMap,它提供了高效的不可變哈希映射。您還需要記住,每次更新此地圖需要像這樣進行同步:

object Database { 
    private var map = new immutable.HashMap[Int, AnyRef] 
    def get(index: Int) = map(index) 
    def insert(index: Int, value: AnyRef) = 
    synchronized(map = map.updated(index, value)) 
} 

的另一種方法是使用併發可變的地圖,像scala.collection.concurrent.TrieMap,不需要額外的鎖定:

object Database { 
    private val map = new concurrent.TrieMap[Int, AnyRef] 
    def get(index: Int) = map(index) 
    def insert(index: Int, value: AnyRef) = map.put(index, value) 
} 
+0

你是說在第一個例子中? ''var'在這裏是必需的,因爲你需要以某種方式更新'數據庫'狀態。 – adamwy

+0

不要固定到具體的實現,除非你必須出於某些特定的原因:'map = Map.empty [Int,AnyRef]'或'map = SortedMap.empty [Int,AnyRef]' – Dima

1

即支持並行插入最好的收藏?有更好的選擇?

使用一成不變的數據結構

TreeMap中是最好的選擇?

是的。

直線前進的方式來實現線程安全是通過使用不可變的數據結構的 。

Scala提供了不可變的數據結構。只需導入scala.collection.immutable._

爲了進行排序使用scala.collection.immutable.TreeMap

This post tells about how to use TreeMap and provide custom ordering

+0

僅使用不可變的數據結構並不能保證代碼是線程安全的。對此模擬數據庫的任何更改都需要與鎖同步,否則某些值將會丟失。 – adamwy

+1

也沒有像'scala.concurrent.immutable'這樣的軟件包。 – adamwy

+0

@adamwy修正了錯字。謝謝 – pamu

0

我不同意上面的建議。無論如何,如果你要有可變狀態,你最好將它隔離到數據容器中,而不是每次都更換容器。

你最好用java容器來達到這個目的。對於hashmap,java ConcurrentHashMap是您的最佳選擇。對於一個被排序的實現,你就必須顯式同步:

object DB { 
    import java.util._ 
    val hashed = new concurrent.ConcurrentHashMap[String, AnyRef] 
    val sorted = Collections.synchronizedMap(new TreeMap[Int, AnyRef]) 
} 

可以import scala.collection.JavaConversions._隱式轉換成那些地圖階,得到的好東西,像mapfilter等等,但是... 你應該不是。在99%的案例中,使用其中的任何一個並不是一個好主意。除了常規的getput(和put/computeIfNotExists對於ConcurrentHashmap的情況)之外的任何東西,實現起來都是不平凡的,並且使用起來很危險。

將這些看作是原始的鍵值容器,而不是全面的scala集合。

+1

「如果你打算有無論如何,可變狀態下,你最好在數據容器內部隔離它,而不是每次都更換容器本身。「你能詳細說明原因嗎?像HAMT這樣的不可變結構並沒有爲一個變更製作所有數據的副本,只是其中的一小部分。另外,OP只需要創建最有可能用於測試目的的假/模擬數據庫,所以在這裏看起來性能並不重要。 – adamwy

+0

我會補充說Scala的'scala.collection.concurrent.TrieMap'可能更具性能,因爲它的所有操作都是無鎖的,而Java'ConcurrentHashMap'似乎鎖定put操作。 – adamwy

+0

那麼,除了性能(不可變集合確實比並發映射快一點),它在語義上就不那麼透明瞭,而且更難推理,因爲每當您更改整個「數據庫」時就會更換它。如果某人碰巧保留了舊地圖的引用,那麼在將其替換爲舊地​​圖後,它將變爲無效。如果兩個更新同時發生並且不是原子的,那麼必須將它們序列化,但是不可變映射的語義並沒有明確說明它是必需的。 根據基準測試,'TrieMap'實際上比'ConcurrentHashMap'慢 – Dima