【问题标题】:SCALA: Which data structures are optimal in which situations when using ".contains()" or ".exists()"?SCALA:在使用“.contains()”或“.exists()”的情况下,哪些数据结构是最佳的?
【发布时间】:2013-05-02 19:56:51
【问题描述】:

我想知道在哪些情况下哪些数据结构最适合使用“包含”或“存在”检查。

我问是因为我来自 Python 背景,并且习惯于使用if x in something: 表达式来处理所有事情。例如,哪些表达式的计算速度最快:

val m = Map(1 -> 1, 2 -> 2, 3 -> 3, 4 -> 4)
                                          //> m  : scala.collection.immutable.Map[Int,Int] = Map(1 -> 1, 2 -> 2, 3 -> 3, 4
                                          //|  -> 4)
val l = List(1,2,3,4)                     //> l  : List[Int] = List(1, 2, 3, 4)
val v = Vector(1,2,3,4)                   //> v  : scala.collection.immutable.Vector[Int] = Vector(1, 2, 3, 4)

m.exists(_._1 == 3)                       //> res0: Boolean = true
m.contains(3)                             //> res1: Boolean = true
l.exists(_ == 3)                          //> res2: Boolean = true
l.contains(3)                             //> res3: Boolean = true
v.exists(_ == 3)                          //> res4: Boolean = true
v.contains(3)                             //> res5: Boolean = true

直观地说,我认为向量应该是最快的随机检查,如果知道检查的值在列表的开头并且有很多数据,那么列表将是最快的。但是,非常欢迎确认或更正。此外,请随时扩展到其他数据结构。

注意:如果您觉得这个问题过于模糊,请告诉我,因为我不确定我的措辞是否正确。

【问题讨论】:

  • 在 Python 中,与所有其他语言一样,当您主要需要成员资格检查时,选择的抽象数据类型是 集合,而不是序列或映射。
  • 检查特定元素不是随机检查,它是对向量/列表/数组的短循环全扫描:取第一个元素,比较,如果不是等于,取第二,比较,...。另一方面,集合和地图上的contains 意味着是恒定时间的(与存在不同,它必须首先应用一些谓词,因此我认为也是线性的)

标签: performance scala data-structures scala-collections


【解决方案1】:

如果你想广泛使用contains,你应该使用Set(或Map)。

AFAIK 没有实现高效(即比 O(n) 更快)exists 的数据结构,因为您传入的闭包甚至可能与内部元素无关。

【讨论】:

    【解决方案2】:

    SetMap(使用默认哈希表实现)是迄今为止最快的 contains,因为它们计算哈希值并立即跳转到正确的位置。例如,如果您想从一千个列表中查找任意字符串,则集合上的 containsListVectorArray 上的 contains 快大约 100 倍。

    使用exists,您真的只关心遍历集合的速度——无论如何您都必须遍历所有内容。在那里,List 通常是冠军(除非你想手动遍历一个数组),但只​​有Set 等等通常特别糟糕(例如,List 上的exists 比 @ 上快 8 倍987654334@ 当每个有 1000 个元素时)。其他的大约是List 的 2.5 倍(通常是 1.5 倍,但 Vector 有一个底层树结构,遍历速度不是那么快)。

    【讨论】:

    • 这与大多数用例无关,但如果您愿意为exists 谓词提供比不透明函数更多的结构,则可以更有效地实现它。如果为可能的关系定义一个简单的 AST,那么基于哈希的结构将擅长相等谓词,而有序结构(TreeMapIntMap 带有陷阱)将擅长相等谓词排序谓词。 Tries 可能擅长前缀匹配谓词,并且您可以获得任意复杂的 DAWG 等。在你的谓词 DSL 中添加变量绑定器,它会更漂亮!
    • @MyseriousDan - exists 是集合库中无结构测试的名称。当然有转换为contains 来表示相等,也有转换为range 来表示树。但那不是exists,那是另外一回事。 (您的意思是回复 gzm0,他声称没有什么比 exists 的 O(n) 更快的了?您的回复在这种情况下会更有意义。)
    • Err,是的,抱歉 :) 但我知道 exists 是一种 API 方法 :P 我只是说如果我们愿意打破不透明的函数模型,我们可以做得更好(但仍然有办法通过隐式转换嵌入任意函数,因此人们可以假装不存在更智能的界面)
    • @MyseriousDan - 确实,字节码对编译器或 JVM 来说不是不透明的,因此即使使用相同的接口,也可以达到该级别。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多