优化实体列表add/remove效率。性能大幅度提高

This commit is contained in:
yhh
2021-04-16 17:48:13 +08:00
parent 5a6d1c72fe
commit 17b36f01b0
14 changed files with 1494 additions and 211 deletions

View File

@@ -0,0 +1,158 @@
module es {
export class Bag<E> implements ImmutableBag<E> {
public size_ = 0;
public length = 0;
private array: Array<E> = [];
constructor(capacity = 64) {
this.length = capacity;
}
removeAt(index: number): E {
const e: E = this.array[index];
this.array[index] = this.array[--this.size_];
this.array[this.size_] = null;
return e;
}
remove(e: E): boolean {
let i: number;
let e2: E;
const size = this.size_;
for (i = 0; i < size; i++) {
e2 = this.array[i];
if (e == e2) {
this.array[i] = this.array[--this.size_];
this.array[this.size_] = null;
return true;
}
}
return false;
}
removeLast(): E {
if (this.size_ > 0) {
const e: E = this.array[--this.size_];
this.array[this.size_] = null;
return e;
}
return null;
}
contains(e: E): boolean {
let i: number;
let size: number;
for (i = 0, size = this.size_; size > i; i++) {
if (e === this.array[i]) {
return true;
}
}
return false;
}
removeAll(bag: ImmutableBag<E>): boolean {
let modified = false;
let i: number;
let j: number;
let l: number;
let e1: E;
let e2: E;
for (i = 0, l = bag.size(); i < l; i++) {
e1 = bag[i];
for (j = 0; j < this.size_; j++) {
e2 = this.array[j];
if (e1 === e2) {
this.removeAt(j);
j--;
modified = true;
break;
}
}
}
return modified;
}
get(index: number): E {
if (index >= this.length) {
throw new Error("ArrayIndexOutOfBoundsException");
}
return this.array[index];
}
safeGet(index: number): E {
if (index >= this.length) {
this.grow((index * 7) / 4 + 1);
}
return this.array[index];
}
size(): number {
return this.size_;
}
getCapacity(): number {
return this.length;
}
isIndexWithinBounds(index: number): boolean {
return index < this.getCapacity();
}
isEmpty(): boolean {
return this.size_ == 0;
}
add(e: E): void {
if (this.size_ === this.length) {
this.grow();
}
this.array[this.size_++] = e;
}
set(index: number, e: E): void {
if (index >= this.length) {
this.grow(index * 2);
}
this.size_ = index + 1;
this.array[index] = e;
}
grow(newCapacity: number = ~~((this.length * 3) / 2) + 1): void {
this.length = ~~newCapacity;
}
ensureCapacity(index: number): void {
if (index >= this.length) {
this.grow(index * 2);
}
}
clear(): void {
let i: number;
let size: number;
for (i = 0, size = this.size_; i < size; i++) {
this.array[i] = null;
}
this.size_ = 0;
}
addAll(items: ImmutableBag<E>): void {
let i: number;
for (i = 0; items.size() > i; i++) {
this.add(items.get(i));
}
}
}
}

View File

@@ -0,0 +1,119 @@
module es {
interface Map<K, V> {
clear(): void;
containsKey(key): boolean;
containsValue(value): boolean;
get(key): V;
isEmpty(): boolean;
put(key, value): void;
remove(key): V;
size(): number;
values(): V[];
}
function decode(key): string {
switch (typeof key) {
case "boolean":
return "" + key;
case "number":
return "" + key;
case "string":
return "" + key;
case "function":
return getClassName(key);
default:
key.uuid = key.uuid ? key.uuid : UUID.randomUUID();
return key.uuid;
}
}
export class HashMap<K, V> implements Map<K, V> {
private map_;
private keys_;
constructor() {
this.clear();
}
clear(): void {
this.map_ = {};
this.keys_ = {};
}
values(): V[] {
const result = [];
const map = this.map_;
for (const key in map) {
result.push(map[key]);
}
return result;
}
contains(value): boolean {
const map = this.map_;
for (const key in map) {
if (value === map[key]) {
return true;
}
}
return false;
}
containsKey(key): boolean {
return decode(key) in this.map_;
}
containsValue(value): boolean {
const map = this.map_;
for (const key in map) {
if (value === map[key]) {
return true;
}
}
return false;
}
get(key: K): V {
return this.map_[decode(key)];
}
isEmpty(): boolean {
return Object.keys(this.map_).length === 0;
}
keys(): K[] {
const keys = this.map_;
const result = [];
for (const key in keys) {
result.push(keys[key]);
}
return result;
}
/**
* if key is a string, use as is, else use key.id_ or key.name
*/
put(key, value): void {
const k = decode(key);
this.map_[k] = value;
this.keys_[k] = key;
}
remove(key): V {
const map = this.map_;
const k = decode(key);
const value = map[k];
delete map[k];
delete this.keys_[k];
return value;
}
size(): number {
return Object.keys(this.map_).length;
}
}
}

View File

@@ -0,0 +1,11 @@
module es {
export interface ImmutableBag<E> {
get(index: number): E;
size(): number;
isEmpty(): boolean;
contains(e: E): boolean;
}
}

293
source/src/Utils/UUID.ts Normal file
View File

@@ -0,0 +1,293 @@
module es {
const hex = [
// hex identity values 0-255
"00",
"01",
"02",
"03",
"04",
"05",
"06",
"07",
"08",
"09",
"0a",
"0b",
"0c",
"0d",
"0e",
"0f",
"10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19",
"1a",
"1b",
"1c",
"1d",
"1e",
"1f",
"20",
"21",
"22",
"23",
"24",
"25",
"26",
"27",
"28",
"29",
"2a",
"2b",
"2c",
"2d",
"2e",
"2f",
"30",
"31",
"32",
"33",
"34",
"35",
"36",
"37",
"38",
"39",
"3a",
"3b",
"3c",
"3d",
"3e",
"3f",
"40",
"41",
"42",
"43",
"44",
"45",
"46",
"47",
"48",
"49",
"4a",
"4b",
"4c",
"4d",
"4e",
"4f",
"50",
"51",
"52",
"53",
"54",
"55",
"56",
"57",
"58",
"59",
"5a",
"5b",
"5c",
"5d",
"5e",
"5f",
"60",
"61",
"62",
"63",
"64",
"65",
"66",
"67",
"68",
"69",
"6a",
"6b",
"6c",
"6d",
"6e",
"6f",
"70",
"71",
"72",
"73",
"74",
"75",
"76",
"77",
"78",
"79",
"7a",
"7b",
"7c",
"7d",
"7e",
"7f",
"80",
"81",
"82",
"83",
"84",
"85",
"86",
"87",
"88",
"89",
"8a",
"8b",
"8c",
"8d",
"8e",
"8f",
"90",
"91",
"92",
"93",
"94",
"95",
"96",
"97",
"98",
"99",
"9a",
"9b",
"9c",
"9d",
"9e",
"9f",
"a0",
"a1",
"a2",
"a3",
"a4",
"a5",
"a6",
"a7",
"a8",
"a9",
"aa",
"ab",
"ac",
"ad",
"ae",
"af",
"b0",
"b1",
"b2",
"b3",
"b4",
"b5",
"b6",
"b7",
"b8",
"b9",
"ba",
"bb",
"bc",
"bd",
"be",
"bf",
"c0",
"c1",
"c2",
"c3",
"c4",
"c5",
"c6",
"c7",
"c8",
"c9",
"ca",
"cb",
"cc",
"cd",
"ce",
"cf",
"d0",
"d1",
"d2",
"d3",
"d4",
"d5",
"d6",
"d7",
"d8",
"d9",
"da",
"db",
"dc",
"dd",
"de",
"df",
"e0",
"e1",
"e2",
"e3",
"e4",
"e5",
"e6",
"e7",
"e8",
"e9",
"ea",
"eb",
"ec",
"ed",
"ee",
"ef",
"f0",
"f1",
"f2",
"f3",
"f4",
"f5",
"f6",
"f7",
"f8",
"f9",
"fa",
"fb",
"fc",
"fd",
"fe",
"ff",
];
export class UUID {
static randomUUID(): string {
const d0 = (Math.random() * 0xffffffff) | 0;
const d1 = (Math.random() * 0xffffffff) | 0;
const d2 = (Math.random() * 0xffffffff) | 0;
const d3 = (Math.random() * 0xffffffff) | 0;
return (
hex[d0 & 0xff] +
hex[(d0 >> 8) & 0xff] +
hex[(d0 >> 16) & 0xff] +
hex[(d0 >> 24) & 0xff] +
"-" +
hex[d1 & 0xff] +
hex[(d1 >> 8) & 0xff] +
"-" +
hex[((d1 >> 16) & 0x0f) | 0x40] +
hex[(d1 >> 24) & 0xff] +
"-" +
hex[(d2 & 0x3f) | 0x80] +
hex[(d2 >> 8) & 0xff] +
"-" +
hex[(d2 >> 16) & 0xff] +
hex[(d2 >> 24) & 0xff] +
hex[d3 & 0xff] +
hex[(d3 >> 8) & 0xff] +
hex[(d3 >> 16) & 0xff] +
hex[(d3 >> 24) & 0xff]
);
}
}
}

View File

@@ -0,0 +1,7 @@
module es {
export interface Class extends Function {}
export function getClassName(klass): string {
return klass.className || klass.name;
}
}