module es { export interface ISet { add(item: T): boolean remove(item: T): boolean contains(item: T): boolean getCount(): number clear(): void toArray(): Array /** * 从当前集合中删除指定集合中的所有元素 * @param other */ exceptWith(other: Array): void /** * 修改当前Set对象,使其只包含该对象和指定数组中的元素 * @param other */ intersectWith(other: Array): void /** * 修改当前的集合对象,使其包含所有存在于自身、指定集合中的元素,或者两者都包含 * @param other */ unionWith(other: Array): void isSubsetOf(other: Array): boolean isSupersetOf(other: Array): boolean overlaps(other: Array): boolean setEquals(other: Array): boolean } interface IBucketsWithCount { Buckets: Array> Count: number } abstract class Set implements ISet { protected buckets: T[][]; protected count: number; constructor(source?: Array) { this.clear(); if (source) source.forEach(value => { this.add(value); }); } abstract getHashCode(item: T): number; abstract areEqual(value1: T, value2: T): boolean; add(item: T) { let hashCode = this.getHashCode(item); let bucket = this.buckets[hashCode]; if (bucket === undefined) { let newBucket = new Array(); newBucket.push(item); this.buckets[hashCode] = newBucket; this.count = this.count + 1; return true; } if (bucket.some((value) => this.areEqual(value,item))) return false; bucket.push(item); this.count = this.count + 1; return true; }; remove(item: T) { let hashCode = this.getHashCode(item); let bucket = this.buckets[hashCode]; if (bucket === undefined) { return false; } let result = false; let newBucket = new Array(); bucket.forEach((value) => { if (!this.areEqual(value, item)) newBucket.push(item); else result = true; }); this.buckets[hashCode] = newBucket; if (result) this.count = this.count - 1; return result; } contains(item: T) { return this.bucketsContains(this.buckets, item) }; getCount() { return this.count; } clear() { this.buckets = new Array>(); this.count = 0; } toArray() { let result = new Array() this.buckets.forEach(value => { value.forEach(inner => { result.push(inner); }); }); return result; } /** * 从当前集合中删除指定集合中的所有元素 * @param other */ exceptWith(other: Array) { if (other) { other.forEach(value => { this.remove(value); }) } } /** * 修改当前Set对象,使其只包含该对象和指定数组中的元素 * @param other */ intersectWith(other: Array) { if (other) { let otherBuckets = this.buildInternalBuckets(other); this.toArray().forEach(value => { if (!this.bucketsContains(otherBuckets.Buckets, value)) this.remove(value); }); } else { this.clear(); } } unionWith(other: Array) { other.forEach(value => { this.add(value); }); } isSubsetOf(other: Array) { let otherBuckets = this.buildInternalBuckets(other); return this.toArray().every(value => this.bucketsContains(otherBuckets.Buckets, value)); } isSupersetOf(other: Array) { return other.every(value => this.contains(value)); } overlaps(other: Array) { return other.some(value => this.contains(value)); } setEquals(other: Array) { let otherBuckets = this.buildInternalBuckets(other); if (otherBuckets.Count !== this.count) return false return other.every(value => this.contains(value)); } private buildInternalBuckets(source: Array): IBucketsWithCount { let internalBuckets = new Array>(); let internalCount = 0; source.forEach(item=> { let hashCode = this.getHashCode(item); let bucket = internalBuckets[hashCode]; if (bucket === undefined) { let newBucket = new Array(); newBucket.push(item); internalBuckets[hashCode] = newBucket; internalCount = internalCount + 1; } else if (!bucket.some((value) => this.areEqual(value, item))) { bucket.push(item); internalCount = internalCount + 1; } }); return { Buckets: internalBuckets, Count: internalCount }; } private bucketsContains(internalBuckets: Array>, item: T) { let hashCode = this.getHashCode(item); let bucket = internalBuckets[hashCode]; if (bucket === undefined) { return false; } return bucket.some((value) => this.areEqual(value, item)); } } export class HashSet extends Set { constructor(source?: Array) { super(source) } getHashCode(item: T) { return item.getHashCode(); } areEqual(value1: T, value2: T) { return value1.equals(value2); } } }