Below are two partial implementations of LinkedHashMap in JavaScript, with test code to populate with lots of keys and remove half the keys at random, then alert() the results. Both implementations add and maintain an index to provide O(1) lookups.

Each is compared to the speed of the equivalent use of Object assuming it supports ordering, which is just to use the JavaScript "delete" operator to remove keys. The first is a straightforward implementation where insert and removal use splice() to modify an Array. This is what most developers would probably implement.

I'd hope not: indexOf on a large Array?

This is approximately 800-1000 times slower than a native Object.

The second leverages native speed better by using two Objects to store the forward and reverse pointers of a classic linked list. I'll stipulate that everyone on this list would arrive at this implementation, but in my opinion a vanishing small number of JavaScript programmers at large would figure it out.

Even so it's 8-10x slower than native.

I notice that you don't count initialization for the native Object
variant. Apart from fixing that, would the following variant help (run, but not tested;-)? It keeps the previous/next key in the key's internal value, to reduce overhead.

Claus

// another partial implementation
(function () {

var sourceDataArr = [];
var keysToRemove = [];

for (var i = 0; i < 30000; i++) {
    sourceDataArr[sourceDataArr.length] = "key" + i;
    sourceDataArr[sourceDataArr.length] = "value" + i;
    if (Math.random(1) > 0.5) {
        keysToRemove[keysToRemove.length] = "key" + i;
    }
}

var orderedMap = {
    init : function (data) {
        this.index = {};
        for (var i = 0; i < data.length; i++) {
                               // [prev,     value,    next]
            this.index[data[i]] = [data[i-2],data[i+1],data[i+2]];
            i++;
        }
        this.firstKey = data[0];
        this.lastKey  = data[data.length-2];
    },
    get : function (key) {
        return this.index[key][1];
    },
    remove : function (key) {
        var which = this.index[key];

        if (which[0]) // is there a previous?
          this.index[which[0]][2] = which[2];
        else // key was first
          this.firstKey = which[2];

        if (which[2]) // is there a next?
          this.index[which[2]][0] = which[0];
        else // key was last
          this.lastKey = which[0];

        delete this.index[key];
    }
};

var start = new Date().getTime();
var sourceDataObj = {};
for (var i = 0; i < sourceDataArr.length; i++) {
  var key = sourceDataArr[i],
      value = sourceDataArr[i+1];
  sourceDataObj[key] = value;
  i++;
}
for (var i = 0; i < keysToRemove.length; i++) {
    delete sourceDataObj[keysToRemove[i]];
}
alert("object: " + (new Date().getTime() - start));

var start = new Date().getTime();
orderedMap.init(sourceDataArr);

for (var i = 0; i < keysToRemove.length; i++) {
    orderedMap.remove(keysToRemove[i]);
}
alert("orderedMap: " + (new Date().getTime() - start));

}());

_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to