关联数组是不是像哈希表一样执行?

Posted

技术标签:

【中文标题】关联数组是不是像哈希表一样执行?【英文标题】:Do associative arrays perform like a hash table?关联数组是否像哈希表一样执行? 【发布时间】:2013-05-25 09:37:42 【问题描述】:

所以想象一下,你在 javascript 中有一个关联数组:

var hashTable = ;

hashTable["red"] = "ff0000";
hashTable["green"] = "00ff00";
hashTable["blue"] = "0000ff";

当您检索这样的值时会发生什么:

var blue = hashTable["blue"];

性能是否与其他语言的哈希表相似?我的意思是,是否有一个实际的哈希函数用于确定属性的位置,或者是否有一个循环搜索,例如:

for (var color in hashTable) 
    if (hashTable.hasOwnProperty(color)) 
        //look for matching key
    

实现是否因浏览器而异?我找不到与此特定主题相关的任何内容。谢谢。

【问题讨论】:

由于属性查找无疑是一个关键的性能领域,您可以放心地打赌,任何现代 JavaScript 引擎都会非常高效地完成它。 它依赖于实现,但线性搜索将是最愚蠢的方法。查找表有很多有效的策略,哈希表只是其中一种。 B树是另一种可能性。 这是 Pointy 评论的关键性能领域。请注意,您没有“关联数组”,而是一个普通对象,您可以通过数组表示法设置和获取属性值。 当我想了解性能时,我会构建简单的测试并进行一些测量。是什么阻止你这样做? 你可以把 JavaScript 对象想象成哈希表... 【参考方案1】:

Javascript 并没有真正的“关联数组”。 返回一个 JavaScript object,它可以具有命名属性,还返回一个 prototype,它允许对象从其他对象继承属性。

因此性能不会很像哈希表,因为属性可能从其原型对象继承,并且按名称搜索给定属性可能需要在找到原型树之前遍历它。

这篇博文也可能提供一些见解:

http://www.devthought.com/2012/01/18/an-object-is-not-a-hash/

【讨论】:

Nit:关联数组是 Map 的另一个名称(不要与 php 的任何东西混淆)。 JavaScript 对象是带有字符串键的 Map - 其中 实现 通常使用某种形式的哈希来实现预期的 O(1) 访问。 对,但我的观点是,如果考虑原型链,可能(基本上)必须遍历多个映射/关联数组/对象,因此性能可能与仅单个地图/对象/任何东西。 假设实现是 O(1) 查找(选择任意界限,没关系),那么查找 C(任何实际情况下的有限界限)级别仍然是 O(1)复杂。虽然,看看现代引擎应用了哪些实现优化会很有趣..(即 Trevor 答案中的链接)。不过,我认为更有趣的是不能不会优化的情况。【参考方案2】:

它在不同的 javascript 引擎中以不同的方式实现,而如今,对象似乎不再由“类字典”数据结构支持。

来自https://developers.google.com/v8/design:

JavaScript 是一种动态编程语言:属性可以动态地添加到对象中,也可以从对象中删除。这意味着对象的属性可能会发生变化。大多数 JavaScript 引擎使用类似字典的数据结构作为对象属性的存储 - 每个属性访问都需要动态查找来解析属性在内存中的位置。这种方法使得在 JavaScript 中访问属性通常比在 Java 和 Smalltalk 等编程语言中访问实例变量要慢得多。在这些语言中,由于对象类定义的固定对象布局,实例变量位于由编译器确定的固定偏移处。访问只是内存加载或存储的问题,通常只需要一条指令。

为了减少访问 JavaScript 属性所需的时间,V8 不使用动态查找来访问属性。相反,V8 在幕后动态创建隐藏类。这个基本思想并不新鲜——基于原型的编程语言 Self 使用映射来做类似的事情。在 V8 中,对象会在添加新属性时更改其隐藏类。

Firefox 的 IonMonkey 做了类似的事情。来自对 Mozilla 开发人员 (http://www.infoq.com/news/2011/05/ionmonkey) 的采访:

动态语言可能没有任何固有的优化优势,但它们确实具有静态语言所没有的有趣优化。例如,当您编写 JavaScript 时,对象以哈希表的形式出现在用户面前,将属性名称映射到值。如果它们真的是这样实现的,它们会很慢并且会占用大量内存。

一个好的引擎能够在内部对看起来相同的对象进行分组,有点像从中提取出一个内部的类似 Java 的类。然后,JIT 可以将对象视为具有实际类型,生成超快速代码,避免昂贵的属性查找。

【讨论】:

Nit:最后一段应该读作:“V8 不 [always] 使用动态查找 ..” 在某些情况下它无法执行此优化 - 微不足道, 当有 expando 属性时。 不错的链接和摘录。我想知道这些优化何时不能应用,在这些情况下做了什么..【参考方案3】:

associative array 一词描述了它的用法:它是一个键值容器,用于将一件事与另一件事相关联。但是术语hash table 描述了它的实现:它使用散列函数来定位底层数组中的元素。在某些使用红黑树或其他数据结构但不使用哈希表的实现中可能存在associative array

【讨论】:

以上是关于关联数组是不是像哈希表一样执行?的主要内容,如果未能解决你的问题,请参考以下文章

VBA中的哈希表/关联数组

JavaScript JavaScript中的简单哈希表(关联数组)

JavaScript中的简单哈希表(关联数组)

redis数据结构之字典/哈希表

PHP学习记录

Java 关联数组