Welche zeitliche Komplexität (in Big-O-Notation) bietet die ES6-Spezifikation für die Schlüsselsammlungen (Set, Map, WeakSet und WeakMap)?
Meine Erwartung, und ich erwarte , dass die meisten Entwickler, ist , dass die Spezifikationen und Implementierungen verwenden würden weitgehend akzeptiert performant Algorithmen, wobei in diesem Fall Set.prototype.has
, add
und delete
für alle O (1) im durchschnittlichen Fall sein. Gleiches gilt für die Map
und Weak–
Äquivalente.
Es ist mir nicht ganz klar, ob die zeitliche Komplexität der Implementierungen vorgeschrieben war, z. B. in der ECMAScript 2015-Sprachspezifikation - 6. Ausgabe - 23.2 Objekte festlegen .
Sofern ich es nicht falsch verstehe (und es ist sicherlich sehr wahrscheinlich, dass ich es tue), sieht es so aus, als ob die ECMA-Spezifikation vorschreibt, dass die Implementierungen (z. B. Set.prototype.has
) einen linearen Zeitalgorithmus ( O (n) ) verwenden sollen. Es würde mich außerordentlich überraschen, dass leistungsfähigere Algorithmen von der Spezifikation nicht vorgeschrieben oder sogar zugelassen würden, und ich wäre sehr an einer Erklärung interessiert, warum dies der Fall ist.
quelle
Antworten:
Ab diesem Absatz sind Sie verlinkt mit:
Sie finden den gleichen Satz für Maps , WeakMaps und WeakSets .
Nein:
Die beobachtbare Semantik hängt hauptsächlich mit der vorhersagbaren Iterationsreihenfolge zusammen (die immer noch effizient und schnell implementiert werden kann ). Die Spezifikation erwartet in der Tat, dass eine Implementierung eine Hash-Tabelle oder ähnliches mit konstantem Zugriff verwendet, obwohl auch Bäume (mit logarithmischer Zugriffskomplexität) zulässig sind.
quelle
Für alle, die neugierig sind, habe ich einen sehr schnellen Benchmark durchgeführt:
const benchmarkMap = size => { console.time('benchmarkMap'); var map = new Map(); for (var i = 0; i < size; i++) map.set(i, i); for (var i = 0; i < size; i++) var x = map.get(i); console.timeEnd('benchmarkMap'); } const benchmarkObj = size => { console.time('benchmarkObj'); var obj = {}; for (var i = 0; i < size; i++) obj[i] = i; for (var i = 0; i < size; i++) var x = obj[i]; console.timeEnd('benchmarkObj'); } var size = 1000000; benchmarkMap(size); benchmarkObj(size);
Ich habe dies einige Male ausgeführt und die folgenden Ergebnisse erzielt:
(2017 MacBook Pro, 2,5 GHz i7 mit 16 G RAM)
benchmarkMap: 189.120ms benchmarkObj: 44.214ms benchmarkMap: 200.817ms benchmarkObj: 38.963ms benchmarkMap: 187.968ms benchmarkObj: 41.633ms benchmarkMap: 186.533ms benchmarkObj: 35.850ms benchmarkMap: 187.339ms benchmarkObj: 44.515ms
quelle
delete
Operationen und beim Vermischen von OperationenMap
viel besser. jsfiddle.net/23hrp0eq