Come viene implementata una mappa hash JavaScript?


88

Attualmente lavoro con OpenLayers e ho un enorme set di dati da disegnare in un livello vettoriale (maggiore di 100000 vettori).

Ora sto cercando di inserire tutti questi vettori in una mappa hash JavaScript per analizzare le prestazioni. Voglio sapere come viene implementata la mappa hash in JavaScript, è una vera funzione hash o solo una funzione wrapping che utilizza una semplice struttura dati e un algoritmo di ricerca?


2
Non esiste una sola implementazione JS, quindi non c'è modo di rispondere a questa domanda. ECMAScript non specifica quale struttura dati utilizzare per gli oggetti, né specifica limitazioni al tempo di accesso. Gli hash sono tipici, ma è possibile utilizzare alberi bilanciati.
outis

1
ES6 ha mappe pure. Il collegamento descrive le differenze tra l'oggetto semplice e la mappa, i dettagli chiave, ecc: MDN JavaScript Map
Den Roman

Risposte:


193

ogni oggetto javascript è una semplice hashmap che accetta una stringa o un simbolo come chiave, quindi puoi scrivere il tuo codice come:

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

L'oggetto javascript è una vera hashmap nella sua implementazione, quindi la complessità nella ricerca è O (1), ma non esiste una hashcode()funzione dedicata per le stringhe javascript, è implementato internamente dal motore javascript (V8, SpiderMonkey, JScript.dll, ecc. .)

Aggiornamento 2020:

javascript oggi supporta anche altri tipi di dati: Mape WeakMap. Si comportano più da vicino come mappe hash rispetto agli oggetti tradizionali.


Perfetto. Prima usavo $ ('div # someDiv'). Data (key, value) e questo è molto più semplice e probabilmente ha un supporto migliore anche per i browser meno recenti. Grazie
Swaroop

c'è un modo per trovare la lunghezza della mappa?
Rolling Stone

2
@Sridhar usa Object.keys (map) .length
otakustay

1
Nota che puoi usare un numero come chiave, map[2] = 'foo'ma viene eseguito internamente a una stringa> map = { '2': 'foo' }
Harry Moreno,

@otakustay, questa è stata una caratteristica fantastica che ho conosciuto oggi :) Ho davvero bisogno di imparare Javascript da vicino.
Pankaj Prakash

31

Gli oggetti JavaScript non possono essere implementati puramente sopra le mappe hash.

Prova questo nella tua console del browser:

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

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

... e li riceverai di nuovo in ordine di inserimento, che è di fatto un comportamento standard .

Le mappe hash intrinsecamente non mantengono l'ordine, quindi le implementazioni JavaScript possono utilizzare le mappe hash in qualche modo, ma se lo fanno, richiederà almeno un indice separato e una contabilità extra per gli inserimenti.

Ecco un video di Lars Bak che spiega perché la v8 non utilizza le mappe hash per implementare gli oggetti .


3
"otakustay è tecnicamente sbagliato, il peggior tipo di sbagliato." È un po 'duro. Potrebbe non essere 1: 1, ma per gli intenti e gli scopi di utilizzare un hash come un dizionario, funziona allo stesso modo.
probabilmente il

1
Voglio solo chiarire che questo può essere vero per alcune implementazioni di JavaScript (come la maggior parte dei browser) ma non necessariamente sempre vero. L'ordine di iterazione sulle chiavi non è definito dagli standard ECMAScript e può essere qualsiasi ordine ed essere comunque un'implementazione JS valida.
TheZ

19

Ecco un modo semplice e conveniente per utilizzare qualcosa di simile alla mappa Java :

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
    }

E per ottenere il valore:

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

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

12

Dovresti provare questo corso Map:

var myMap = new Map();

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

myMap.size; // 3

// getting the values
myMap.get("1");    // "value associated with "value1"
myMap.get("2");       // "value associated with "value1"
myMap.get("3");      // "value associated with "value3"

Avviso: chiave e valore possono essere di qualsiasi tipo.

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


4

Mentre i semplici vecchi oggetti JavaScript possono essere usati come mappe, di solito sono implementati in modo da preservare l'ordine di inserimento per la compatibilità con la maggior parte dei browser (vedi la risposta di Craig Barnes) e quindi non sono semplici mappe hash.

ES6 introduce mappe appropriate (vedi MDN JavaScript Map ) di cui lo standard dice :

L'oggetto mappa deve essere implementato utilizzando tabelle hash o altri meccanismi che, in media, forniscono tempi di accesso sublineari rispetto al numero di elementi nella raccolta.


1
<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>

0

Stavo riscontrando il problema in cui avevo il json con alcune chiavi comuni. Volevo raggruppare tutti i valori con la stessa chiave. Dopo un po 'di navigazione ho trovato il pacchetto hashmap . Il che è davvero utile.

Per raggruppare l'elemento con la stessa chiave, ho usato multi(key:*, value:*, key2:*, value2:*, ...).

Questo pacchetto è in qualche modo simile alla raccolta Java Hashmap, ma non potente come Java Hashmap.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.