收藏我只是模擬的API在內存假的數據庫,並使用scala.collection.mutable.HashMap[Int, AnyRef]
關於斯卡拉
即支持併發插入的最佳採集簡單的問題?有更好的選擇?
假設我需要另一種類似的集合,如
Map[Int, AnyRef]
,但這次鍵需要排序。 TreeMap是最佳選擇嗎?
在此先感謝
收藏我只是模擬的API在內存假的數據庫,並使用scala.collection.mutable.HashMap[Int, AnyRef]
關於斯卡拉
即支持併發插入的最佳採集簡單的問題?有更好的選擇?
假設我需要另一種類似的集合,如Map[Int, AnyRef]
,但這次鍵需要排序。 TreeMap是最佳選擇嗎?
在此先感謝
你有兩個選擇這裏。
您可以使用不可變的數據結構,如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)
}
即支持並行插入最好的收藏?有更好的選擇?
使用一成不變的數據結構
TreeMap中是最好的選擇?
是的。
直線前進的方式來實現線程安全是通過使用不可變的數據結構的 。
Scala提供了不可變的數據結構。只需導入scala.collection.immutable._
。
爲了進行排序使用scala.collection.immutable.TreeMap
This post tells about how to use TreeMap and provide custom ordering
我不同意上面的建議。無論如何,如果你要有可變狀態,你最好將它隔離到數據容器中,而不是每次都更換容器。
你最好用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._
隱式轉換成那些地圖階,得到的好東西,像map
,filter
等等,但是... 你應該不是。在99%的案例中,使用其中的任何一個並不是一個好主意。除了常規的get
和put
(和put/computeIfNotExists
對於ConcurrentHashmap
的情況)之外的任何東西,實現起來都是不平凡的,並且使用起來很危險。
將這些看作是原始的鍵值容器,而不是全面的scala集合。
「如果你打算有無論如何,可變狀態下,你最好在數據容器內部隔離它,而不是每次都更換容器本身。「你能詳細說明原因嗎?像HAMT這樣的不可變結構並沒有爲一個變更製作所有數據的副本,只是其中的一小部分。另外,OP只需要創建最有可能用於測試目的的假/模擬數據庫,所以在這裏看起來性能並不重要。 – adamwy
我會補充說Scala的'scala.collection.concurrent.TrieMap'可能更具性能,因爲它的所有操作都是無鎖的,而Java'ConcurrentHashMap'似乎鎖定put操作。 – adamwy
那麼,除了性能(不可變集合確實比並發映射快一點),它在語義上就不那麼透明瞭,而且更難推理,因爲每當您更改整個「數據庫」時就會更換它。如果某人碰巧保留了舊地圖的引用,那麼在將其替換爲舊地圖後,它將變爲無效。如果兩個更新同時發生並且不是原子的,那麼必須將它們序列化,但是不可變映射的語義並沒有明確說明它是必需的。 根據基準測試,'TrieMap'實際上比'ConcurrentHashMap'慢 – Dima
你是說在第一個例子中? ''var'在這裏是必需的,因爲你需要以某種方式更新'數據庫'狀態。 – adamwy
不要固定到具體的實現,除非你必須出於某些特定的原因:'map = Map.empty [Int,AnyRef]'或'map = SortedMap.empty [Int,AnyRef]' – Dima