UNPKG

google-closure-library

Version:
217 lines (182 loc) 5.23 kB
/** * @license * Copyright The Closure Library Authors. * SPDX-License-Identifier: Apache-2.0 */ /** * @fileoverview Datastructure: Hash Map. * * This file provides a goog.structs.Map interface based on native Map. */ goog.module('goog.ui.Map'); goog.module.declareLegacyNamespace(); /** * Class for Hash Map datastructure. * @param {*=} map Map or Object to initialize the map with. * @constructor * @template K, V */ const UiMap = function(map = undefined) { /** @private @const {!Map<K, V>} */ this.map_ = new Map(); const argLength = arguments.length; if (argLength > 1) { if (argLength % 2) { throw new Error('Uneven number of arguments'); } for (let i = 0; i < argLength; i += 2) { this.set(arguments[i], arguments[i + 1]); } } else if (map) { this.addAll(/** @type {!Object} */ (map)); } }; /** * @return {number} The number of key-value pairs in the map. */ UiMap.prototype.getCount = function() { return this.map_.size; }; /** * Returns the values of the map. * @return {!Array<V>} The values in the map. */ UiMap.prototype.getValues = function() { return Array.from(this.map_.values()); }; /** * Returns the keys of the map. * @return {!Array<K>} Array of string values. */ UiMap.prototype.getKeys = function() { return Array.from(this.map_.keys()); }; /** * Whether the map contains the given key. * @param {K} key The key to check for. * @return {boolean} Whether the map contains the key. */ UiMap.prototype.containsKey = function(key) { return this.map_.has(key); }; /** * Whether the map contains the given value. This is O(n). * @param {V} val The value to check for. * @return {boolean} Whether the map contains the value. */ UiMap.prototype.containsValue = function(val) { // NOTE: goog.structs.Map uses == instead of ===. return this.getValues().some((v) => v == val); }; /** * Whether this map is equal to the argument map. * @param {!UiMap} otherMap The map against which to test equality. * @param {function(V, V): boolean=} equalityFn Optional equality function * to test equality of values. If not specified, this will test whether * the values contained in each map are identical objects. * @return {boolean} Whether the maps are equal. */ UiMap.prototype.equals = function( otherMap, equalityFn = (a, b) => a === b) { if (this === otherMap) { return true; } if (this.map_.size != otherMap.getCount()) { return false; } return this.getKeys().every((key) => { return equalityFn(this.map_.get(key), otherMap.get(key)); }); }; /** * @return {boolean} Whether the map is empty. */ UiMap.prototype.isEmpty = function() { return this.map_.size == 0; }; /** * Removes all key-value pairs from the map. */ UiMap.prototype.clear = function() { this.map_.clear(); }; /** * Removes a key-value pair based on the key. This is O(logN) amortized due to * updating the keys array whenever the count becomes half the size of the keys * in the keys array. * @param {K} key The key to remove. * @return {boolean} Whether object was removed. */ UiMap.prototype.remove = function(key) { return this.map_.delete(key); }; /** * Returns the value for the given key. If the key is not found and the default * value is not given this will return `undefined`. * @param {*} key The key to get the value for. * @param {DEFAULT=} defaultValue The value to return if no item is found for * the given key, defaults to undefined. * @return {V|DEFAULT} The value for the given key. * @template DEFAULT */ UiMap.prototype.get = function(key, defaultValue = undefined) { if (this.map_.has(key)) { return this.map_.get(key); } return defaultValue; }; /** * Adds a key-value pair to the map. * @param {*} key The key. * @param {V} value The value to add. * @return {!THIS} Some subclasses return a value. * @this {THIS} * @template THIS */ UiMap.prototype.set = function(key, value) { const self = /** @type {!UiMap} */ (this); self.map_.set(key, value); return self; }; /** * Adds multiple key-value pairs from another goog.ui.Map or Object. * @param {!Object<K, V>} map Object containing the data to add. */ UiMap.prototype.addAll = function(map) { if (map instanceof UiMap) { for (const [key, val] of map.map_) { this.map_.set(key, val); } } else if (!!map) { for (const [key, val] of Object.entries(map)) { this.map_.set(key, val); } } }; /** * Calls the given function on each entry in the map. * @param {function(this:T, V, K, (!Map|!UiMap<K,V>|null))} callbackFn * @param {T=} thisArg The value of "this" inside callbackFn. * @template T */ UiMap.prototype.forEach = function(callbackFn, thisArg = this) { this.map_.forEach((val, key) => callbackFn.call(thisArg, val, key, this)); }; /** * Clones a map and returns a new map. * @return {!UiMap} A new map with the same key-value pairs. */ UiMap.prototype.clone = function() { return new UiMap(this); }; /** * @return {!Object} Object representation of the map. */ UiMap.prototype.toObject = function() { const obj = {}; for (const [key, val] of this.map_) { obj[key] = val; } return obj; }; exports = UiMap;