Show:
                            /**
                             * The Collection Utility
                             *
                             * @module aui-collection
                             * @submodule aui-map
                             */
                            
                            var Lang = A.Lang,
                                AArray = A.Array,
                                AObject = A.Object;
                            
                            /**
                             * A base class for HashMap.
                             *
                             * @class A.HashMap
                             * @extends Base
                             * @param {Object} config Object literal specifying widget configuration
                             *     properties.
                             * @constructor
                             */
                            var HashMap = A.Base.create('map', A.Base, [], {
                                FALSE: A.guid(),
                                NAN: A.guid(),
                                NULL: A.guid(),
                                NUMBER: A.guid(),
                                OBJECT: A.guid(),
                                TRUE: A.guid(),
                                UNDEFINED: A.guid(),
                            
                                _keys: null,
                                _objects: null,
                                _size: 0,
                                _values: null,
                            
                                /**
                                 * Construction logic executed during `A.HashMap` instantiation. Lifecycle.
                                 *
                                 * @method initializer
                                 * @protected
                                 */
                                initializer: function() {
                                    var instance = this;
                            
                                    instance.publish({
                                        clear: {
                                            defaultFn: instance._defClearFn
                                        },
                                        put: {
                                            defaultFn: instance._defPutFn
                                        },
                                        remove: {
                                            defaultFn: instance._defRemoveFn
                                        }
                                    });
                            
                                    instance._keys = {};
                                    instance._values = {};
                                    instance._objects = [];
                                },
                            
                                /**
                                 * Fires the `clear` custom event.
                                 *
                                 * @method clear
                                 */
                                clear: function() {
                                    this.fire('clear');
                                },
                            
                                /**
                                 * Returns the value from a key in this map.
                                 *
                                 * @method getValue
                                 * @param key
                                 * @return {Object}
                                 */
                                getValue: function(key) {
                                    var instance = this;
                            
                                    return instance._values[instance._getHash(key)];
                                },
                            
                                /**
                                 * Checks if this map has the specified key.
                                 *
                                 * @method has
                                 * @param key
                                 * @param opt_hash
                                 * @return {Boolean}
                                 */
                                has: function(key, opt_hash) {
                                    var instance = this;
                            
                                    return instance._values.hasOwnProperty(
                                        opt_hash || instance._getHash(key));
                                },
                            
                                /**
                                 * Returns `true` if this map contains a certain value.
                                 *
                                 * @method hasValue
                                 * @param value
                                 * @return {Boolean}
                                 */
                                hasValue: function(value) {
                                    var found = false;
                            
                                    AObject.some(this._values, function(val) {
                                        found = val === value;
                                        return found;
                                    });
                            
                                    return found;
                                },
                            
                                /**
                                 * Returns a collection of the keys contained in this map.
                                 *
                                 * @method keys
                                 * @return {Object}
                                 */
                                keys: function() {
                                    return AObject.values(this._keys);
                                },
                            
                                /**
                                 * Returns `true` if this map contains no key-value mappings.
                                 *
                                 * @method isEmpty
                                 * @return {Boolean}
                                 */
                                isEmpty: function() {
                                    return this._size === 0;
                                },
                            
                                /**
                                 * Fires the `put` custom event.
                                 *
                                 * @method put
                                 * @param key
                                 * @param value
                                 * @param opt_hash
                                 */
                                put: function(key, value, opt_hash) {
                                    this.fire('put', {
                                        key: key,
                                        value: value,
                                        hash: opt_hash
                                    });
                                },
                            
                                /**
                                 * Copies all of the mappings from the specified map to this map.
                                 *
                                 * @method putAll
                                 * @param map
                                 */
                                putAll: function(map) {
                                    var instance = this;
                            
                                    AObject.each(map, function(value, key) {
                                        instance.put(key, value);
                                    });
                                },
                            
                                /**
                                 * Fires the `remove` custom event.
                                 *
                                 * @method remove
                                 * @param key
                                 * @param opt_hash
                                 * @return {Object}
                                 */
                                remove: function(key, opt_hash) {
                                    var instance = this,
                                        oldValue = instance.getValue(key);
                            
                                    instance.fire('remove', {
                                        key: key,
                                        value: oldValue,
                                        hash: opt_hash
                                    });
                            
                                    return oldValue;
                                },
                            
                                /**
                                 * Returns the number of key-value mappings in this map.
                                 *
                                 * @method size
                                 * @return {Number}
                                 */
                                size: function() {
                                    return this._size;
                                },
                            
                                /**
                                 * Returns a collection of the values contained in this map.
                                 *
                                 * @method values
                                 * @return {Object}
                                 */
                                values: function() {
                                    return AObject.values(this._values);
                                },
                            
                                /**
                                 * Implements the `clear` custom event behavior. Removes all of the mappings
                                 * from this map.
                                 *
                                 * @method _defClearFn
                                 * @protected
                                 */
                                _defClearFn: function() {
                                    var instance = this;
                            
                                    AArray.each(instance.keys(), function(key) {
                                        instance.remove(key);
                                    });
                            
                                    instance._size = 0;
                                },
                            
                                /**
                                 * Implements the `put` custom event behavior. Associates the specified
                                 * value with the specified key in this map.
                                 *
                                 * @method _defPutFn
                                 * @param event
                                 * @protected
                                 */
                                _defPutFn: function(event) {
                                    var instance = this,
                                        hash = event.hash;
                            
                                    if (Lang.isUndefined(hash)) {
                                        hash = instance._getHash(event.key);
                                    }
                            
                                    if (!instance.has(event.key)) {
                                        instance._size++;
                                    }
                                    instance._keys[hash] = event.key;
                                    instance._values[hash] = event.value;
                                },
                            
                                /**
                                 * Implements the `remove` custom event behavior. Removes the mapping for a
                                 * key from this map if it is present.
                                 *
                                 * @method _defRemoveFn
                                 * @param event
                                 * @protected
                                 */
                                _defRemoveFn: function(event) {
                                    var instance = this,
                                        key = event.key,
                                        keys = instance._keys,
                                        values = instance._values,
                                        hash = event.hash,
                                        objects,
                                        oldValue,
                                        valueIndex;
                            
                                    if (instance.has(key)) {
                                        if (Lang.isUndefined(hash)) {
                                            hash = instance._getHash(key);
                                        }
                            
                                        oldValue = values[hash];
                            
                                        delete values[hash];
                                        delete keys[hash];
                            
                                        if (!instance._isObjectWithHashCode(oldValue)) {
                                            objects = instance._objects;
                                            valueIndex = AArray.indexOf(objects, key);
                                            if (valueIndex > -1) {
                                                objects[valueIndex] = null;
                                            }
                                        }
                            
                                        instance._size--;
                                    }
                                    event.value = oldValue;
                                },
                            
                                /**
                                 * Returns a hash in `String` format based in the function argument.
                                 *
                                 * @method _getHash
                                 * @param value
                                 * @protected
                                 * @return {String}
                                 */
                                _getHash: function(value) {
                                    var instance = this;
                            
                                    // A reliable way for ECMAScript code to test if a value X is a NaN
                                    // is an expression of the form X !== X. The result will be true if
                                    // and only if X is a NaN.
                                    if (value !== value) {
                                        value = instance.NAN;
                                    }
                                    else if (value === false) {
                                        value = instance.FALSE;
                                    }
                                    else if (value === null) {
                                        value = instance.NULL;
                                    }
                                    else if (value === true) {
                                        value = instance.TRUE;
                                    }
                                    else if (value === undefined) {
                                        value = instance.UNDEFINED;
                                    }
                                    else if (Lang.isObject(value)) {
                                        value = instance._getHashForObject(value);
                                    }
                                    else if (Lang.isNumber(value) ||
                                        value === Number.POSITIVE_INFINITY ||
                                        value === Number.NEGATIVE_INFINITY) {
                            
                                        value = instance.NUMBER + '_' + value;
                                    }
                            
                                    return String(value);
                                },
                            
                                /**
                                 * Returns a hash from an `Object`.
                                 *
                                 * @method _getHashForObject
                                 * @param value
                                 * @protected
                                 */
                                _getHashForObject: function(value) {
                                    var instance = this,
                                        valueIndex;
                            
                                    if (instance._isObjectWithHashCode(value)) {
                                        return instance.OBJECT + '_' + value.hashCode();
                                    }
                                    // When object hash code is missing, falls back to O(N) implementation
                                    valueIndex = AArray.indexOf(instance._objects, value);
                            
                                    return instance.OBJECT + '_' +
                                        ((valueIndex > -1) ? valueIndex :
                                        instance._objects.push(value) - 1);
                                },
                            
                                /**
                                 * Returns `true` if the argument's hash code is a `Function`.
                                 *
                                 * @method _isObjectWithHashCode
                                 * @param value
                                 * @protected
                                 * @return {Boolean}
                                 */
                                _isObjectWithHashCode: function(value) {
                                    if (!Lang.isObject(value)) {
                                        return false;
                                    }
                                    return Lang.isFunction(value.hashCode);
                                }
                            }, {});
                            
                            A.Map = HashMap;