| 407 | * values (in the entire collection) are unique. |
| 408 | */ |
| 409 | export class UniqueValueMultiKeyMap<K, V> { |
| 410 | // A map from a key to the first value corresponding to this key. |
| 411 | private kvMap = new Map<K, V>(); |
| 412 | // A map that acts as a linked list of values - each value maps to the next value in this "linked |
| 413 | // list" (this only works if values are unique). Allocated lazily to avoid memory consumption when |
| 414 | // there are no duplicated values. |
| 415 | private _vMap: Map<V, V> | undefined = undefined; |
| 416 | |
| 417 | has(key: K): boolean { |
| 418 | return this.kvMap.has(key); |
| 419 | } |
| 420 | |
| 421 | delete(key: K): boolean { |
| 422 | if (!this.has(key)) return false; |
| 423 | |
| 424 | const value = this.kvMap.get(key)!; |
| 425 | if (this._vMap !== undefined && this._vMap.has(value)) { |
| 426 | this.kvMap.set(key, this._vMap.get(value)!); |
| 427 | this._vMap.delete(value); |
| 428 | } else { |
| 429 | this.kvMap.delete(key); |
| 430 | } |
| 431 | |
| 432 | return true; |
| 433 | } |
| 434 | |
| 435 | get(key: K): V | undefined { |
| 436 | return this.kvMap.get(key); |
| 437 | } |
| 438 | |
| 439 | set(key: K, value: V): void { |
| 440 | if (this.kvMap.has(key)) { |
| 441 | let prevValue = this.kvMap.get(key)!; |
| 442 | |
| 443 | // Note: we don't use `assertNotSame`, because the value needs to be stringified even if |
| 444 | // there is no error which can freeze the browser for large values (see #58509). |
| 445 | if (ngDevMode && prevValue === value) { |
| 446 | throw new Error(`Detected a duplicated value ${value} for the key ${key}`); |
| 447 | } |
| 448 | |
| 449 | if (this._vMap === undefined) { |
| 450 | this._vMap = new Map(); |
| 451 | } |
| 452 | |
| 453 | const vMap = this._vMap; |
| 454 | while (vMap.has(prevValue)) { |
| 455 | prevValue = vMap.get(prevValue)!; |
| 456 | } |
| 457 | vMap.set(prevValue, value); |
| 458 | } else { |
| 459 | this.kvMap.set(key, value); |
| 460 | } |
| 461 | } |
| 462 | |
| 463 | forEach(cb: (v: V, k: K) => void) { |
| 464 | for (let [key, value] of this.kvMap) { |
| 465 | cb(value, key); |
| 466 | if (this._vMap !== undefined) { |
nothing calls this directly
no outgoing calls
no test coverage detected
searching dependent graphs…