Home Reference Source Test

src/main/generic/utils/array/LimitHashSet.js

/**
 * @template V
 * @implements {Iterable.<V>}
 */
class LimitHashSet {
    /**
     * @param {number} limit
     * @param {function(o: object): string} [fnHash]
     */
    constructor(limit, fnHash = LimitHashSet._hash) {
        if (limit <= 0) throw new Error('Invalid limit');
        /** @type {number} */
        this._limit = limit;
        /** @type {function(o: object): string} */
        this._fnHash = fnHash;
        /** @type {UniqueLinkedList.<V>} */
        this._list = new UniqueLinkedList(fnHash);
    }

    /**
     * @param {{hashCode: function():string}|*} o
     * @returns {string}
     * @private
     */
    static _hash(o) {
        if (o === null || o === undefined) return o;
        return o.hashCode ? o.hashCode() : o.toString();
    }


    /**
     * @param {V|*} value
     */
    add(value) {
        this._list.push(value, true);
        if (this._list.length > this._limit) {
            this._list.shift();
        }
    }

    /**
     * @param {Iterable.<V|*>} collection
     */
    addAll(collection) {
        for (const value of collection) {
            this.add(value);
        }
    }

    /**
     * @param {V|*} value
     * @returns {V|*}
     */
    get(value) {
        return this._list.get(value);
    }

    /**
     * @param {V|*} value
     */
    remove(value) {
        this._list.remove(value);
    }

    /**
     * @param {Array.<V|*>} collection
     */
    removeAll(collection) {
        for (const value of collection) {
            this.remove(value);
        }
    }

    /**
     * @returns {void}
     */
    clear() {
        this._list.clear();
    }

    /**
     * @param {V|*} value
     * @returns {boolean}
     */
    contains(value) {
        return this._list.contains(value);
    }

    /**
     * @returns {Array.<V|*>}
     */
    values() {
        return Array.from(this._list.iterator());
    }

    /**
     * @returns {Iterator.<V|*>}
     */
    valueIterator() {
        return this._list.iterator();
    }

    /**
     * @returns {Iterator.<V|*>}
     */
    [Symbol.iterator]() {
        return this.valueIterator();
    }

    /**
     * @returns {number}
     */
    get length() {
        return this._list.length;
    }

    /**
     * @returns {boolean}
     */
    isEmpty() {
        return this._list.length === 0;
    }
}
Class.register(LimitHashSet);