JavaScript 哈希映射是如何实现的?

Posted

技术标签:

【中文标题】JavaScript 哈希映射是如何实现的?【英文标题】:How is a JavaScript hash map implemented? 【发布时间】:2012-02-11 06:08:24 【问题描述】:

我目前使用 OpenLayers,并且有大量数据要绘制到矢量图层(超过 100000 个矢量)。

我现在正尝试将所有这些向量放入 javascript 哈希映射中以分析性能。我想知道JavaScript中的hash map是如何实现的,是真正的hash函数还是只是一个使用简单数据结构和搜索算法的包装函数?

【问题讨论】:

JS实现不止一种,所以没办法回答。 ECMAScript 没有指定对象使用什么数据结构,也没有指定访问时间的限制。散列是典型的,但可以使用平衡树。 ES6 有纯 Maps。该链接描述了普通对象和 Map 之间的区别、关键细节等:MDN JavaScript Map 【参考方案1】:

每个 javascript object 都是一个简单的 hashmap,它接受字符串或 Symbol 作为其键,因此您可以将代码编写为:

var map = ;
// add a item
map[key1] = value1;
// or remove it
delete map[key1];
// or determine whether a key exists
key1 in map;

javascript对象在其实现上是一个真正的hashmap,所以搜索的复杂度是O(1),但是对于javascript字符串没有专门的hashcode()函数,它是由javascript引擎内部实现的(V8,SpiderMonkey,JScript .dll等...)

2020 年更新:

现在的javascript 也支持其他数据类型:MapWeakMap。与传统对象相比,它们的行为更接近于哈希映射。

【讨论】:

完美。我之前使用过 $('div#someDiv').data(key, value) ,这个更简单,并且可能对旧浏览器也有更好的支持。谢谢 有没有办法找到地图的长度? @Sridhar 使用 Object.keys(map).length 请注意,您可以使用数字作为键 map[2] = 'foo',但它会在内部转换为字符串 > map = '2': 'foo' @otakustay 这是我今天才知道的超酷功能 :) 真的我需要密切学习 Javascript。【参考方案2】:

这是一种使用类似于 Java map 的简单方便的方法:

var map= 
    'map_name_1': map_value_1,
    'map_name_2': map_value_2,
    'map_name_3': map_value_3,
    'map_name_4': map_value_4
    

并获得价值:

alert( map['map_name_1'] );    // fives the value of map_value_1

......  etc  .....

【讨论】:

【参考方案3】:

JavaScript 对象不能纯粹在哈希映射之上实现。

在您的浏览器控制台中试试这个:

var foo = 
    a: true,
    b: true,
    z: true,
    c: true


for (var i in foo) 
    console.log(i);

...您会按照插入顺序收到它们,即de facto standard 行为。

哈希映射本质上不维护顺序,因此 JavaScript 实现可能以某种方式使用哈希映射,但如果这样做,它至少需要一个单独的索引和一些额外的插入簿记。

这是Lars Bak explaining why v8 doesn't use hash maps to implement objects的视频。

【讨论】:

"otakustay 在技术上是错误的,是最糟糕的错误。"这有点苛刻。它可能不是 1:1,但出于使用像字典这样的哈希的意图和目的,它以相同的方式工作。 只是想澄清一下,这对于 JavaScript 的某些实现(例如大多数浏览器)可能是正确的,但不一定总是正确的。键的迭代顺序不是由 ECMAScript 标准定义的,可以是任何顺序,但仍然是有效的 JS 实现。 与某些实现是否使用散列的问题不同,它们是否还保留插入顺序的键列表以方便用户使用与原始问题无关。【参考方案4】:
<html>
<head>
<script type="text/javascript">
function test()
var map= 'm1': 12,'m2': 13,'m3': 14,'m4': 15
     alert(map['m3']);

</script>
</head>
<body>
<input type="button" value="click" onclick="test()"/>
</body>
</html>

【讨论】:

【参考方案5】:

虽然普通的旧 JavaScript 对象可以用作映射,但它们通常以保留插入顺序的方式实现以与大多数浏览器兼容(请参阅 Craig Barnes 的回答),因此不是简单的哈希映射。

ES6 引入了正确的 Maps(参见 MDN JavaScript Map),其中 standard says:

Map 对象必须使用哈希表或其他机制来实现,平均而言,这些机制提供的访问时间与集合中的元素数量呈次线性关系。

【讨论】:

【参考方案6】:

你要不要试试这门课Map:

var myMap = new Map();

// setting the values
myMap.set("1", 'value1');
myMap.set("2", 'value2');
myMap.set("3", 'value3');

console.log(`Map size: $myMap.size`); // 3

// getting the values
console.log(`Key: "1", Value: $myMap.get("1")`);    // "value associated with "value1"
console.log(`Key: "2", Value: $myMap.get("2")`);    // "value associated with "value2"
console.log(`Key: "3", Value: $myMap.get("3")`);    // "value associated with "value3"

注意:keyvalue 可以是任何类型。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map

【讨论】:

【参考方案7】:

我遇到了带有一些通用键的 json 的问题。我想将所有具有相同键的值分组。经过一番冲浪,我找到了hashmap package。这真的很有帮助。

为了对具有相同键的元素进行分组,我使用了multi(key:*, value:*, key2:*, value2:*, ...)

这个包有点类似于 Java Hashmap 集合,但没有 Java Hashmap 强大。

【讨论】:

以上是关于JavaScript 哈希映射是如何实现的?的主要内容,如果未能解决你的问题,请参考以下文章

我如何将 djb2 映射到哈希表?

哈希映射

如何更改哈希映射中键的值? [复制]

哈希算法从原理到实战

哈希算法:你会如何存储重要数据

面试常问:分布式缓存如何实现一致性哈希?