Scala有没有可以解决这个问题的类?我正在考虑使用Array[Array[_]]
,因为它很适合我的需求。
我还有其他选择吗?我相信使用Map[(Int,Int),_]
会太慢,因为它具有线性访问时间。
答案 0 :(得分:4)
HashMap几乎可以做到。这个Scala collection performance页面非常有用。
答案 1 :(得分:4)
地图实现中的访问(除了ListMap)当然不是线性的(非常小的地图,少于4个元素,确实是线性搜索,但对于这么小的地图来说,这是一个非常快速的实现,即O(N)具有非常小的N和非常小的k因子。但是当表增长时,使用不同的算法,渐近地更快,通常是O(log(N))或O(1)。
然而,如果你需要的是一个表/矩阵,在某种意义上它包含满足0< = i<的密钥(i,j)的数据了。 m,0< = j< n,(从1开始也可以)一般地图可能不是最好的选择。如果表格已满,那么所有(i,j)都有值。然后基于数组,Array [Array [_]]或甚至单个数组可能会好得多。如果你想要专门的东西,也许你不想实现完整的Map接口。
答案 2 :(得分:1)
为了获得最佳性能,您可能希望尽可能避免垃圾收集器(GC)。这意味着不创建元组对象(i,j)而不是装箱基元。如果你的表将被完全填充(不稀疏),那么你对阵列数组的想法是合理的。然而,为了获得最佳性能,我会选择didierd的想法并将所有内容打包到一个带有访问器的阵列中。这是一个可能的实现:
// specialize A to avoid boxing primitives such as Int, Double, ...
class Table[@specialized A: Manifest](numRows: Int, numCols: Int) {
val data = new Array[A](numRows*numCols)
def checkIndices(i: Int, j: Int) {
require (i >= 0 && i < numRows && j >= 0 && j < numCols)
}
def apply(i: Int, j: Int): A = {
checkIndices(i, j)
data(i*numCols + j)
}
def update(i: Int, j: Int, x: A) {
checkIndices(i, j)
data(i*numCols + j) = x
}
}
您可以像这样自然地使用它(请注意从特殊apply
和update
方法获得的漂亮语法):
scala> val table = new Table[Double](2, 2)
table: Table[Double] = Table$mcD$sp@4d22366e
scala> table(0, 0) = 3.0
scala> table(1, 1) = table(0, 0) + 2.0
scala> table(2, 1)
java.lang.IllegalArgumentException: requirement failed
...
另一方面,如果表是稀疏的,那么最好使用Map
来为所有空条目保存内存。请注意,尽管Map
具有快速update
和apply
方法(几乎不变),但它们仍然比数组访问慢得多(主要是由于GC上的压力; {{1} }不是专用的,键和值都必须是堆分配的。)