Path: blob/trunk/third_party/closure/goog/structs/set.js
4501 views
/**1* @license2* Copyright The Closure Library Authors.3* SPDX-License-Identifier: Apache-2.04*/56/**7* @fileoverview Datastructure: Set.8*9*10* This class implements a set data structure. Adding and removing is O(1). It11* supports both object and primitive values. Be careful because you can add12* both 1 and new Number(1), because these are not the same. You can even add13* multiple new Number(1) because these are not equal.14*/151617goog.provide('goog.structs.Set');1819goog.require('goog.structs');20goog.require('goog.structs.Collection');21goog.require('goog.structs.Map');22goog.requireType('goog.iter.Iterator');23goog.require('goog.utils');2425/**26* A set that can contain both primitives and objects. Adding and removing27* elements is O(1). Primitives are treated as identical if they have the same28* type and convert to the same string. Objects are treated as identical only29* if they are references to the same object. WARNING: A goog.structs.Set can30* contain both 1 and (new Number(1)), because they are not the same. WARNING:31* Adding (new Number(1)) twice will yield two distinct elements, because they32* are two different objects. WARNING: Any object that is added to a33* goog.structs.Set will be modified! Because goog.getUid() is used to34* identify objects, every object in the set will be mutated.35* @param {Array<T>|Object<?,T>=} opt_values Initial values to start with.36* @constructor37* @implements {goog.structs.Collection<T>}38* @implements {Iterable<T>}39* @final40* @template T41* @deprecated This type is misleading: use ES6 Set instead.42*/43goog.structs.Set = function(opt_values) {44'use strict';45this.map_ = new goog.structs.Map();464748/**49* The number of items in this set.50* @const {number}51*/52this.size = 0;5354if (opt_values) {55this.addAll(opt_values);56}57};5859/**60* A function that returns a unique id.61* @private @const {function(?Object): number}62*/63goog.structs.Set.getUid_ = goog.utils.getUid;646566/**67* Obtains a unique key for an element of the set. Primitives will yield the68* same key if they have the same type and convert to the same string. Object69* references will yield the same key only if they refer to the same object.70* @param {*} val Object or primitive value to get a key for.71* @return {string} A unique key for this value/object.72* @private73*/74goog.structs.Set.getKey_ = function(val) {75'use strict';76var type = typeof val;77if (type == 'object' && val || type == 'function') {78return 'o' + goog.structs.Set.getUid_(/** @type {Object} */ (val));79} else {80return type.slice(0, 1) + val;81}82};838485/**86* @return {number} The number of elements in the set.87* @override88* @deprecated Use the `size` property instead, for alignment with ES6 Set.89*/90goog.structs.Set.prototype.getCount = function() {91'use strict';92return this.map_.size;93};949596/**97* Add a primitive or an object to the set.98* @param {T} element The primitive or object to add.99* @override100*/101goog.structs.Set.prototype.add = function(element) {102'use strict';103this.map_.set(goog.structs.Set.getKey_(element), element);104this.setSizeInternal_(this.map_.size);105};106107108/**109* Adds all the values in the given collection to this set.110* @param {Array<T>|goog.structs.Collection<T>|Object<?,T>} col A collection111* containing the elements to add.112* @deprecated Use `goog.collections.sets.addAll(thisSet, col)` instead,113* converting Objects to their values using `Object.values`, for alignment114* with ES6 Set.115*/116goog.structs.Set.prototype.addAll = function(col) {117'use strict';118var values = goog.structs.getValues(col);119var l = values.length;120for (var i = 0; i < l; i++) {121this.add(values[i]);122}123this.setSizeInternal_(this.map_.size);124};125126127/**128* Removes all values in the given collection from this set.129* @param {Array<T>|goog.structs.Collection<T>|Object<?,T>} col A collection130* containing the elements to remove.131* @deprecated Use `goog.collections.sets.removeAll(thisSet, col)` instead,132* converting Objects to their values using `Object.values`, for alignment133* with ES6 Set.134*/135goog.structs.Set.prototype.removeAll = function(col) {136'use strict';137var values = goog.structs.getValues(col);138var l = values.length;139for (var i = 0; i < l; i++) {140this.remove(values[i]);141}142this.setSizeInternal_(this.map_.size);143};144145146/**147* Removes the given element from this set.148* @param {T} element The primitive or object to remove.149* @return {boolean} Whether the element was found and removed.150*/151goog.structs.Set.prototype.delete = function(element) {152'use strict';153const rv = this.map_.remove(goog.structs.Set.getKey_(element));154this.setSizeInternal_(this.map_.size);155return rv;156};157158/**159* Removes the given element from this set.160* @param {T} element The primitive or object to remove.161* @return {boolean} Whether the element was found and removed.162* @override163* @deprecated Use `delete`, for alignment with ES6 Set.164*/165goog.structs.Set.prototype.remove = function(element) {166'use strict';167return this.delete(element);168};169170171/**172* Removes all elements from this set.173*/174goog.structs.Set.prototype.clear = function() {175'use strict';176this.map_.clear();177this.setSizeInternal_(0);178};179180181/**182* Tests whether this set is empty.183* @return {boolean} True if there are no elements in this set.184* @deprecated Use the size property and compare against 0, for alignment with185* ES6 Set.186*/187goog.structs.Set.prototype.isEmpty = function() {188'use strict';189return this.map_.size === 0;190};191192193/**194* Tests whether this set contains the given element.195* @param {T} element The primitive or object to test for.196* @return {boolean} True if this set contains the given element.197*/198goog.structs.Set.prototype.has = function(element) {199'use strict';200return this.map_.containsKey(goog.structs.Set.getKey_(element));201};202203/**204* Tests whether this set contains the given element.205* @param {T} element The primitive or object to test for.206* @return {boolean} True if this set contains the given element.207* @override208* @deprecated Use `has` instead, for alignment with ES6 Set.209*/210goog.structs.Set.prototype.contains = function(element) {211'use strict';212return this.map_.containsKey(goog.structs.Set.getKey_(element));213};214215216/**217* Tests whether this set contains all the values in a given collection.218* Repeated elements in the collection are ignored, e.g. (new219* goog.structs.Set([1, 2])).containsAll([1, 1]) is True.220* @param {goog.structs.Collection<T>|Object} col A collection-like object.221* @return {boolean} True if the set contains all elements.222* @deprecated Use `goog.collections.sets.hasAll(thisSet, col)`, converting223* Objects to arrays using Object.values, for alignment with ES6 Set.224*/225goog.structs.Set.prototype.containsAll = function(col) {226'use strict';227return goog.structs.every(col, this.contains, this);228};229230231/**232* Finds all values that are present in both this set and the given collection.233* @param {Array<S>|Object<?,S>} col A collection.234* @return {!goog.structs.Set<T|S>} A new set containing all the values235* (primitives or objects) present in both this set and the given236* collection.237* @template S238* @deprecated Use `goog.collections.sets.intersection(thisSet, col)`,239* converting Objects to arrays using Object.values, instead for alignment240* with ES6 Set.241*/242goog.structs.Set.prototype.intersection = function(col) {243'use strict';244var result = new goog.structs.Set();245246var values = goog.structs.getValues(col);247for (var i = 0; i < values.length; i++) {248var value = values[i];249if (this.contains(value)) {250result.add(value);251}252}253254return result;255};256257258/**259* Finds all values that are present in this set and not in the given260* collection.261* @param {Array<T>|goog.structs.Collection<T>|Object<?,T>} col A collection.262* @return {!goog.structs.Set} A new set containing all the values263* (primitives or objects) present in this set but not in the given264* collection.265*/266goog.structs.Set.prototype.difference = function(col) {267'use strict';268var result = this.clone();269result.removeAll(col);270return result;271};272273274/**275* Returns an array containing all the elements in this set.276* @return {!Array<T>} An array containing all the elements in this set.277* @deprecated Use `Array.from(set.values())` instead, for alignment with ES6278* Set.279*/280goog.structs.Set.prototype.getValues = function() {281'use strict';282return this.map_.getValues();283};284285/**286* @returns {!IteratorIterable<T>} An ES6 Iterator that iterates over the values287* in the set.288*/289goog.structs.Set.prototype.values = function() {290'use strict';291return this.map_.values();292};293294/**295* Creates a shallow clone of this set.296* @return {!goog.structs.Set<T>} A new set containing all the same elements as297* this set.298* @deprecated Use `new Set(thisSet.values())` for alignment with ES6 Set.299*/300goog.structs.Set.prototype.clone = function() {301'use strict';302return new goog.structs.Set(this);303};304305306/**307* Tests whether the given collection consists of the same elements as this set,308* regardless of order, without repetition. Primitives are treated as equal if309* they have the same type and convert to the same string; objects are treated310* as equal if they are references to the same object. This operation is O(n).311* @param {goog.structs.Collection<T>|Object} col A collection.312* @return {boolean} True if the given collection consists of the same elements313* as this set, regardless of order, without repetition.314* @deprecated Use `goog.collections.equals(thisSet, col)`, converting Objects315* to arrays using Object.values, instead for alignment with ES6 Set.316*/317goog.structs.Set.prototype.equals = function(col) {318'use strict';319return this.getCount() == goog.structs.getCount(col) && this.isSubsetOf(col);320};321322323/**324* Tests whether the given collection contains all the elements in this set.325* Primitives are treated as equal if they have the same type and convert to the326* same string; objects are treated as equal if they are references to the same327* object. This operation is O(n).328* @param {goog.structs.Collection<T>|Object} col A collection.329* @return {boolean} True if this set is a subset of the given collection.330* @deprecated Use `goog.collections.isSubsetOf(thisSet, col)`, converting331* Objects to arrays using Object.values, instead for alignment with ES6332* Set.333*/334goog.structs.Set.prototype.isSubsetOf = function(col) {335'use strict';336var colCount = goog.structs.getCount(col);337if (this.getCount() > colCount) {338return false;339}340if (!(col instanceof goog.structs.Set) && colCount > 5) {341// Convert to a goog.structs.Set so that goog.structs.contains runs in342// O(1) time instead of O(n) time.343col = new goog.structs.Set(col);344}345return goog.structs.every(this, function(value) {346'use strict';347return goog.structs.contains(col, value);348});349};350351352/**353* Returns an iterator that iterates over the elements in this set.354* @param {boolean=} opt_keys This argument is ignored.355* @return {!goog.iter.Iterator} An iterator over the elements in this set.356* @deprecated Call `values` and use native iteration, for alignment with ES6357* Set.358*/359goog.structs.Set.prototype.__iterator__ = function(opt_keys) {360'use strict';361return this.map_.__iterator__(false);362};363364/**365* @return {!IteratorIterable<T>} An ES6 Iterator that iterates over the values366* in the set.367*/368goog.structs.Set.prototype[Symbol.iterator] = function() {369return this.values();370};371372/**373* Assigns to the size property to isolate supressions of const assignment374* to only where they are needed.375* @param {number} newSize The size to update to.376* @private377*/378goog.structs.Set.prototype.setSizeInternal_ = function(newSize) {379/** @suppress {const} */380this.size = newSize;381};382383384