function createMap() {
    var mappings = {}; // map from hash to array of {key, value} bindings.
    var count = 0;

    /**
     * Get the number of elements in the map.
     */
    function size() {
        return count;
    }

    /**
     * Get the value associated with the given key. If there is
     * no mapping for the key, return the ifNotFound argument (which
     * defaults to undefined).
     */
    function get(key, ifNotFound) {
        var candidates = mappings[hash(key)];

        if (!candidates) {
            return ifNotFound;
        }

        for (var i = candidates.length - 1; i >= 0; i--) {
            var one = candidates[i];
            if (one.key === key) {
                return one.value;
            }
        }

        return ifNotFound;
    }

    /**
     * Set the value associated with the given key to the given value,
     * and return the previously associated value. If there was no
     * previous mapping for the key, return the ifNotFound argument
     * (which defaults to undefined).
     */
    function set(key, value, ifNotFound) {
        var h = hash(key);
        var candidates = mappings[h];

        if (!candidates) {
            candidates = mappings[h] = [];
        }

        for (var i = candidates.length - 1; i >= 0; i--) {
            var one = candidates[i];
            if (one.key === key) {
                var result = one.value;
                one.value = value;
                return result;
            }
        }

        candidates.push({ key: key, value: value });
        count++;
        return ifNotFound;
    }

    /**
     * Return true if there is a mapping for the given key or false
     * if not.
     */
    function has(key) {
        // Use the internal variable "mappings" as the ifNotFound
        // value, since we know it can't appear in the map.
        return get(key, mappings) !== mappings;
    }

    /**
     * Remove the mapping for the given key, returning its formerly
     * associated value or the ifNotFound value if the key wasn't
     * formerly mapped.
     */
    function remove(key, ifNotFound) {
        var candidates = mappings[hash(key)];

        if (!candidates) {
            return ifNotFound;
        }

        for (var i = candidates.length - 1; i >= 0; i--) {
            var one = candidates[i];
            if (one.key === key) {
                var result = one.value;
                candidates.splice(i, 1);
                count--;
                return result;
            }
        }

        return ifNotFound;
    }

    /**
     * Call the given callback on each mapping. The callback is called
     * with two arguments, (key, value). There is no guarantee about the
     * order of callbacks.
     */
    function forEach(callback) {
        Object.keys(mappings).forEach(forHash);

        function forHash(hash) {
            var arr = mappings[hash];
            for (var i = arr.length - 1; i >= 0; i--) {
                var one = arr[i];
                callback(one.key, one.value);
            }
        }
    }

    return {
        forEach: forEach,
        has:     has,
        get:     get,
        remove:  remove,
        set:     set,
        size:    size
    };
}
/**
 * Construct a map (association list) keyed by object/value identity.
 */
Construct a map (association list) keyed by object/value identity.
Construct a map ( association list ) keyed by object / value identity .
function createMap() {
    var mappings = {}; 
    var count = 0;
    function size() {
        return count;
    }
    function get(key, ifNotFound) {
        var candidates = mappings[hash(key)];
        if (!candidates) {
            return ifNotFound;
        }
        for (var i = candidates.length - 1; i >= 0; i--) {
            var one = candidates[i];
            if (one.key === key) {
                return one.value;
            }
        }
        return ifNotFound;
    }
    function set(key, value, ifNotFound) {
        var h = hash(key);
        var candidates = mappings[h];
        if (!candidates) {
            candidates = mappings[h] = [];
        }
        for (var i = candidates.length - 1; i >= 0; i--) {
            var one = candidates[i];
            if (one.key === key) {
                var result = one.value;
                one.value = value;
                return result;
            }
        }
        candidates.push({ key: key, value: value });
        count++;
        return ifNotFound;
    }
    function has(key) {
        return get(key, mappings) !== mappings;
    }
    function remove(key, ifNotFound) {
        var candidates = mappings[hash(key)];
        if (!candidates) {
            return ifNotFound;
        }
        for (var i = candidates.length - 1; i >= 0; i--) {
            var one = candidates[i];
            if (one.key === key) {
                var result = one.value;
                candidates.splice(i, 1);
                count--;
                return result;
            }
        }
        return ifNotFound;
    }
    function forEach(callback) {
        Object.keys(mappings).forEach(forHash);
        function forHash(hash) {
            var arr = mappings[hash];
            for (var i = arr.length - 1; i >= 0; i--) {
                var one = arr[i];
                callback(one.key, one.value);
            }
        }
    }
    return {
        forEach: forEach,
        has:     has,
        get:     get,
        remove:  remove,
        set:     set,
        size:    size
    };
}
function createMap ( ) { var mappings = { } ; var count = 0 ; function size ( ) { return count ; } function get ( key , ifNotFound ) { var candidates = mappings [ hash ( key ) ] ; if ( ! candidates ) { return ifNotFound ; } for ( var i = candidates . length - 1 ; i >= 0 ; i -- ) { var one = candidates [ i ] ; if ( one . key === key ) { return one . value ; } } return ifNotFound ; } function set ( key , value , ifNotFound ) { var h = hash ( key ) ; var candidates = mappings [ h ] ; if ( ! candidates ) { candidates = mappings [ h ] = [ ] ; } for ( var i = candidates . length - 1 ; i >= 0 ; i -- ) { var one = candidates [ i ] ; if ( one . key === key ) { var result = one . value ; one . value = value ; return result ; } } candidates . push ( { key : key , value : value } ) ; count ++ ; return ifNotFound ; } function has ( key ) { return get ( key , mappings ) !== mappings ; } function remove ( key , ifNotFound ) { var candidates = mappings [ hash ( key ) ] ; if ( ! candidates ) { return ifNotFound ; } for ( var i = candidates . length - 1 ; i >= 0 ; i -- ) { var one = candidates [ i ] ; if ( one . key === key ) { var result = one . value ; candidates . splice ( i , 1 ) ; count -- ; return result ; } } return ifNotFound ; } function forEach ( callback ) { Object . keys ( mappings ) . forEach ( forHash ) ; function forHash ( hash ) { var arr = mappings [ hash ] ; for ( var i = arr . length - 1 ; i >= 0 ; i -- ) { var one = arr [ i ] ; callback ( one . key , one . value ) ; } } } return { forEach : forEach , has : has , get : get , remove : remove , set : set , size : size } ; }
Construct a map (association list) keyed by object/value identity.
Construct a map ( association list ) keyed by object / value identity .
// map from hash to array of {key, value} bindings. /**
     * Get the number of elements in the map.
     */ /**
     * Get the value associated with the given key. If there is
     * no mapping for the key, return the ifNotFound argument (which
     * defaults to undefined).
     */ /**
     * Set the value associated with the given key to the given value,
     * and return the previously associated value. If there was no
     * previous mapping for the key, return the ifNotFound argument
     * (which defaults to undefined).
     */ /**
     * Return true if there is a mapping for the given key or false
     * if not.
     */ // Use the internal variable "mappings" as the ifNotFound // value, since we know it can't appear in the map. /**
     * Remove the mapping for the given key, returning its formerly
     * associated value or the ifNotFound value if the key wasn't
     * formerly mapped.
     */ /**
     * Call the given callback on each mapping. The callback is called
     * with two arguments, (key, value). There is no guarantee about the
     * order of callbacks.
     */