【问题标题】:What structures to use to create constant access time immutable table in Scala?使用什么结构在 Scala 中创建恒定访问时间不可变表?
【发布时间】:2011-08-05 10:51:52
【问题描述】:

Scala 有什么类可以处理这个问题吗?我正在考虑使用Array[Array[_]],因为它非常适合我的需求。

我还有什么其他选择?我相信使用Map[(Int,Int),_] 会太慢,因为它具有线性访问时间。

【问题讨论】:

  • 好吧,如果你有一个好的哈希值,HashMap (Map[ ] ) 有恒定的时间。
  • 默认Map 具有恒定时间访问,因为它基于哈希表。不要假设集合性能 - 要么测试,要么查找可用的文档。

标签: scala collections


【解决方案1】:

Map 实现中的访问(除了ListMap)肯定不是线性的(非常小的地图,少于 4 个元素,确实可以进行线性搜索,但对于如此小的地图来说,这是一个非常快速的实现,即 O( N) 具有非常小的 N 和非常小的 k 因子。但是当表增长时,使用不同的算法,渐近快得多,通常为 O(log(N)) 或 O(1)。

然而,如果您需要的是一个表/矩阵,从某种意义上说,它包含满足 0

【讨论】:

  • 不,对地图的访问不是“肯定不是线性的”。
  • 您好,didierd,我喜欢您的回答并对其进行了一些扩展。一条评论:从数学上讲,对于小 N 来说 O(N) 是没有意义的,因为大 O 渐近符号仅在 N 很大时才有意义,而且我们总是忽略常量前因子。从某种意义上说,小型数据结构的所有性能特征都可能被这些预因素所吞噬。
  • @尼古拉斯。也许我说的不对。我的意思是这比线性要好得多。我会做出改变。
  • @Kipton。好吧,你是一个线性搜索算法,它是 O(N),并且只将它应用于小表。但事实上,关键不是它是 O(N),而是它是 kxN 且速度快。
  • @didierd 我认为我们同意,但为了澄清我的观点,Big-O 是一种精确的数学符号,仅适用于 N 趋于无穷大的极限。 en.wikipedia.org/wiki/Big_O_notation
【解决方案2】:

HashMap 几乎可以做到。这个Scala collection performance 页面非常有用。

【讨论】:

    【解决方案3】:

    为了获得最佳性能,您可能希望尽可能避免使用垃圾收集器 (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
      } 
    }
    

    您可以像这样自然地使用它(注意您从特殊的 applyupdate 方法中获得的漂亮语法):

    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 具有快速的updateapply 方法(几乎恒定),但它们仍然比数组访问慢很多(主要是由于GC 的压力;Map 不是专门的,这两个键并且值必须是堆分配的)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-26
      • 2016-04-04
      • 2011-08-18
      • 1970-01-01
      • 2021-12-18
      • 1970-01-01
      • 2015-05-25
      • 1970-01-01
      相关资源
      最近更新 更多