2016-12-25 120 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