github.com/whatap/golib@v0.0.22/util/hmap/StringIntLinkedMap.go (about) 1 package hmap 2 3 import ( 4 "bytes" 5 "sort" 6 "sync" 7 8 "github.com/whatap/golib/util/hash" 9 ) 10 11 type StringIntLinkedMap struct { 12 table []*StringIntLinkedEntry 13 header *StringIntLinkedEntry 14 count int 15 threshold int 16 loadFactor float32 17 lock sync.Mutex 18 max int 19 NONE int32 20 } 21 22 func NewStringIntLinkedMap() *StringIntLinkedMap { 23 24 initCapacity := DEFAULT_CAPACITY 25 loadFactor := DEFAULT_LOAD_FACTOR 26 27 this := new(StringIntLinkedMap) 28 this.loadFactor = float32(loadFactor) 29 this.table = make([]*StringIntLinkedEntry, initCapacity) 30 this.header = &StringIntLinkedEntry{} 31 this.header.link_next = this.header 32 this.header.link_prev = this.header 33 this.threshold = int(float64(initCapacity) * loadFactor) 34 35 this.NONE = 0 36 37 return this 38 } 39 40 func (this *StringIntLinkedMap) SetNullValue(none int32) *StringIntLinkedMap { 41 this.NONE = none 42 return this 43 } 44 45 func (this *StringIntLinkedMap) Size() int { 46 return this.count 47 } 48 49 func (this *StringIntLinkedMap) KeyArray() []string { 50 this.lock.Lock() 51 defer this.lock.Unlock() 52 53 _keys := make([]string, this.Size()) 54 en := this.Keys() 55 for i := 0; i < len(_keys); i++ { 56 _keys[i] = en.NextString() 57 } 58 return _keys 59 } 60 61 func (this *StringIntLinkedMap) Keys() StringEnumer { 62 return &StringIntLinkedEnumer{parent: this, entry: this.header.link_next} 63 } 64 func (this *StringIntLinkedMap) Values() Enumeration { 65 return &StringIntLinkedEnumer{parent: this, entry: this.header.link_next, isEntry: false} 66 } 67 func (this *StringIntLinkedMap) Entries() Enumeration { 68 return &StringIntLinkedEnumer{parent: this, entry: this.header.link_next, isEntry: true} 69 } 70 71 func (this *StringIntLinkedMap) ContainsValue(value int32) bool { 72 this.lock.Lock() 73 defer this.lock.Unlock() 74 75 tab := this.table 76 77 for i := len(tab) - 1; i > 0; i-- { 78 for e := tab[i]; e != nil; e = e.hash_next { 79 if e.value == value { 80 return true 81 } 82 } 83 } 84 return false 85 } 86 87 func (this *StringIntLinkedMap) ContainsKey(key string) bool { 88 this.lock.Lock() 89 defer this.lock.Unlock() 90 91 tab := this.table 92 index := this.hash(key) % uint(len(tab)) 93 for e := tab[index]; e != nil; e = e.hash_next { 94 if e.key == key { 95 return true 96 } 97 } 98 return false 99 100 } 101 func (this *StringIntLinkedMap) Get(key string) int32 { 102 this.lock.Lock() 103 defer this.lock.Unlock() 104 105 tab := this.table 106 index := this.hash(key) % uint(len(tab)) 107 for e := tab[index]; e != nil; e = e.hash_next { 108 if e.key == key { 109 return e.value 110 } 111 } 112 return this.NONE 113 } 114 115 func (this *StringIntLinkedMap) GetFirstKey() string { 116 this.lock.Lock() 117 defer this.lock.Unlock() 118 119 return this.header.link_next.key 120 } 121 122 func (this *StringIntLinkedMap) GetLastKey() string { 123 this.lock.Lock() 124 defer this.lock.Unlock() 125 return this.header.link_prev.key 126 } 127 128 func (this *StringIntLinkedMap) GetFirstValue() interface{} { 129 this.lock.Lock() 130 defer this.lock.Unlock() 131 132 if this.IsEmpty() { 133 return this.NONE 134 } 135 136 return this.header.link_next.value 137 } 138 139 func (this *StringIntLinkedMap) GetLastValue() interface{} { 140 this.lock.Lock() 141 defer this.lock.Unlock() 142 143 if this.IsEmpty() { 144 return this.NONE 145 } 146 147 return this.header.link_prev.value 148 } 149 func (this *StringIntLinkedMap) hash(key string) uint { 150 return uint(hash.HashStr(key)) 151 } 152 153 func (this *StringIntLinkedMap) rehash() { 154 oldCapacity := len(this.table) 155 oldMap := this.table 156 newCapacity := oldCapacity*2 + 1 157 newMap := make([]*StringIntLinkedEntry, newCapacity) 158 this.threshold = int(float32(newCapacity) * this.loadFactor) 159 this.table = newMap 160 for i := oldCapacity; i > 0; i-- { 161 for old := oldMap[i-1]; old != nil; { 162 e := old 163 old = old.hash_next 164 index := uint(e.keyHash % uint(newCapacity)) 165 e.hash_next = newMap[index] 166 newMap[index] = e 167 } 168 } 169 } 170 171 func (this *StringIntLinkedMap) SetMax(max int) *StringIntLinkedMap { 172 this.max = max 173 return this 174 } 175 func (this *StringIntLinkedMap) Put(key string, value int32) int32 { 176 this.lock.Lock() 177 defer this.lock.Unlock() 178 return this.put(key, value, PUT_LAST) 179 } 180 func (this *StringIntLinkedMap) PutLast(key string, value int32) int32 { 181 this.lock.Lock() 182 defer this.lock.Unlock() 183 return this.put(key, value, PUT_FORCE_LAST) 184 } 185 func (this *StringIntLinkedMap) PutFirst(key string, value int32) int32 { 186 this.lock.Lock() 187 defer this.lock.Unlock() 188 return this.put(key, value, PUT_FORCE_FIRST) 189 } 190 func (this *StringIntLinkedMap) put(key string, value int32, m PUT_MODE) int32 { 191 if key == "" { 192 return this.NONE 193 } 194 195 tab := this.table 196 keyHash := this.hash(key) 197 index := keyHash % uint(len(tab)) 198 for e := tab[index]; e != nil; e = e.hash_next { 199 if e.key == key { 200 old := e.value 201 e.value = value 202 switch m { 203 case PUT_FORCE_FIRST: 204 if this.header.link_next != e { 205 this.unchain(e) 206 this.chain(this.header, this.header.link_next, e) 207 } 208 case PUT_FORCE_LAST: 209 if this.header.link_prev != e { 210 this.unchain(e) 211 this.chain(this.header.link_prev, this.header, e) 212 } 213 } 214 return old 215 } 216 } 217 if this.max > 0 { 218 switch m { 219 case PUT_FORCE_FIRST, PUT_FIRST: 220 for this.count >= this.max { 221 k := this.header.link_prev.key 222 this.remove(k) 223 } 224 case PUT_FORCE_LAST, PUT_LAST: 225 for this.count >= this.max { 226 // removeFirst(); 227 k := this.header.link_next.key 228 this.remove(k) 229 } 230 break 231 } 232 } 233 if this.count >= this.threshold { 234 this.rehash() 235 tab = this.table 236 index = keyHash % uint(len(tab)) 237 } 238 e := &StringIntLinkedEntry{key: key, keyHash: keyHash, value: value, hash_next: tab[index]} 239 tab[index] = e 240 switch m { 241 case PUT_FORCE_FIRST, PUT_FIRST: 242 this.chain(this.header, this.header.link_next, e) 243 case PUT_FORCE_LAST, PUT_LAST: 244 this.chain(this.header.link_prev, this.header, e) 245 } 246 this.count++ 247 return this.NONE 248 } 249 250 func (this *StringIntLinkedMap) Add(key string, value int32) int32 { 251 return this._add(key, value, PUT_LAST) 252 } 253 254 func (this *StringIntLinkedMap) AddLast(key string, value int32) int32 { 255 return this._add(key, value, PUT_FORCE_LAST) 256 } 257 258 func (this *StringIntLinkedMap) AddFirst(key string, value int32) int32 { 259 return this._add(key, value, PUT_FORCE_FIRST) 260 } 261 func (this *StringIntLinkedMap) _add(key string, value int32, m PUT_MODE) int32 { 262 this.lock.Lock() 263 defer this.lock.Unlock() 264 265 if key == "" { 266 return this.NONE 267 } 268 269 tab := this.table 270 keyHash := this.hash(key) 271 index := keyHash % uint(len(tab)) 272 for e := tab[index]; e != nil; e = e.hash_next { 273 if e.key == key { 274 old := e.value 275 e.value = value 276 switch m { 277 case PUT_FORCE_FIRST: 278 if this.header.link_next != e { 279 this.unchain(e) 280 this.chain(this.header, this.header.link_next, e) 281 } 282 case PUT_FORCE_LAST: 283 if this.header.link_prev != e { 284 this.unchain(e) 285 this.chain(this.header.link_prev, this.header, e) 286 } 287 } 288 return old 289 } 290 } 291 if this.max > 0 { 292 switch m { 293 case PUT_FORCE_FIRST, PUT_FIRST: 294 for this.count >= this.max { 295 k := this.header.link_prev.key 296 this.remove(k) 297 } 298 case PUT_FORCE_LAST, PUT_LAST: 299 for this.count >= this.max { 300 // removeFirst(); 301 k := this.header.link_next.key 302 this.remove(k) 303 } 304 break 305 } 306 } 307 if this.count >= this.threshold { 308 this.rehash() 309 tab = this.table 310 index = keyHash % uint(len(tab)) 311 } 312 e := &StringIntLinkedEntry{key: key, keyHash: keyHash, value: value, hash_next: tab[index]} 313 tab[index] = e 314 switch m { 315 case PUT_FORCE_FIRST, PUT_FIRST: 316 this.chain(this.header, this.header.link_next, e) 317 case PUT_FORCE_LAST, PUT_LAST: 318 this.chain(this.header.link_prev, this.header, e) 319 } 320 this.count++ 321 322 return this.NONE 323 } 324 325 func (this *StringIntLinkedMap) Remove(key string) interface{} { 326 this.lock.Lock() 327 defer this.lock.Unlock() 328 329 return this.remove(key) 330 } 331 func (this *StringIntLinkedMap) RemoveFirst() interface{} { 332 if this.IsEmpty() { 333 return this.NONE 334 } 335 this.lock.Lock() 336 defer this.lock.Unlock() 337 return this.remove(this.header.link_next.key) 338 } 339 340 func (this *StringIntLinkedMap) RemoveLast() interface{} { 341 if this.IsEmpty() { 342 return this.NONE 343 } 344 this.lock.Lock() 345 defer this.lock.Unlock() 346 return this.remove(this.header.link_prev.key) 347 } 348 349 func (this *StringIntLinkedMap) remove(key string) interface{} { 350 351 tab := this.table 352 index := this.hash(key) % uint(len(tab)) 353 e := tab[index] 354 var prev *StringIntLinkedEntry = nil 355 for e != nil { 356 if e.key == key { 357 if prev != nil { 358 prev.hash_next = e.hash_next 359 } else { 360 tab[index] = e.hash_next 361 } 362 this.count-- 363 oldValue := e.value 364 e.value = this.NONE 365 // 366 this.unchain(e) 367 return oldValue 368 } 369 prev = e 370 e = e.hash_next 371 } 372 return this.NONE 373 } 374 375 func (this *StringIntLinkedMap) IsEmpty() bool { 376 return this.count == 0 377 } 378 func (this *StringIntLinkedMap) IsFull() bool { 379 return this.max > 0 && this.max <= this.count 380 } 381 382 func (this *StringIntLinkedMap) Clear() { 383 this.lock.Lock() 384 defer this.lock.Unlock() 385 this.clear() 386 } 387 func (this *StringIntLinkedMap) clear() { 388 tab := this.table 389 for index := len(tab) - 1; index >= 0; index-- { 390 tab[index] = nil 391 } 392 this.header.link_next = this.header 393 this.header.link_prev = this.header 394 this.count = 0 395 } 396 397 func (this *StringIntLinkedMap) chain(link_prev *StringIntLinkedEntry, link_next *StringIntLinkedEntry, e *StringIntLinkedEntry) { 398 e.link_prev = link_prev 399 e.link_next = link_next 400 link_prev.link_next = e 401 link_next.link_prev = e 402 } 403 404 func (this *StringIntLinkedMap) unchain(e *StringIntLinkedEntry) { 405 e.link_prev.link_next = e.link_next 406 e.link_next.link_prev = e.link_prev 407 e.link_prev = nil 408 e.link_next = nil 409 } 410 411 type StringIntSortable struct { 412 compare func(a, b string) bool 413 data []*StringIntLinkedEntry 414 } 415 416 func (this StringIntSortable) Len() int { 417 return len(this.data) 418 } 419 func (this StringIntSortable) Less(i, j int) bool { 420 return this.compare(this.data[i].GetKey(), this.data[j].GetKey()) 421 } 422 423 func (this StringIntSortable) Swap(i, j int) { 424 this.data[i], this.data[j] = this.data[j], this.data[i] 425 } 426 427 func (this *StringIntLinkedMap) Sort(c func(k1, k2 string) bool) { 428 this.lock.Lock() 429 defer this.lock.Unlock() 430 431 sz := this.Size() 432 list := make([]*StringIntLinkedEntry, sz) 433 en := this.Entries() 434 for i := 0; i < sz; i++ { 435 list[i] = en.NextElement().(*StringIntLinkedEntry) 436 } 437 sort.Sort(StringIntSortable{compare: c, data: list}) 438 439 this.clear() 440 for i := 0; i < sz; i++ { 441 this.put(list[i].GetKey(), list[i].GetValue(), PUT_LAST) 442 } 443 } 444 445 func (this *StringIntLinkedMap) ToString() string { 446 this.lock.Lock() 447 defer this.lock.Unlock() 448 449 var buffer bytes.Buffer 450 x := this.Entries() 451 buffer.WriteString("{") 452 for i := 0; x.HasMoreElements(); i++ { 453 if i > 0 { 454 buffer.WriteString(", ") 455 } 456 e := x.NextElement().(*StringIntLinkedEntry) 457 buffer.WriteString(e.ToString()) 458 } 459 buffer.WriteString("}") 460 return buffer.String() 461 } 462 463 type StringIntLinkedEnumer struct { 464 parent *StringIntLinkedMap 465 entry *StringIntLinkedEntry 466 isEntry bool 467 Type int 468 } 469 470 func NewStringIntLinkedEnumer(parent *StringIntLinkedMap, entry *StringIntLinkedEntry, Type int) *StringIntLinkedEnumer { 471 p := new(StringIntLinkedEnumer) 472 p.parent = parent 473 p.entry = entry 474 p.Type = Type 475 476 return p 477 } 478 func (this *StringIntLinkedEnumer) HasMoreElements() bool { 479 return this.entry != nil && this.parent.header != this.entry 480 } 481 func (this *StringIntLinkedEnumer) NextElement() interface{} { 482 if this.HasMoreElements() { 483 e := this.entry 484 this.entry = e.link_next 485 486 switch this.Type { 487 case ELEMENT_TYPE_KEYS: 488 return e.key 489 case ELEMENT_TYPE_VALUES: 490 return e.value 491 default: 492 return e 493 } 494 } 495 return nil 496 } 497 498 func (this *StringIntLinkedEnumer) NextInt() int32 { 499 if this.HasMoreElements() { 500 e := this.entry 501 this.entry = e.link_next 502 return e.value 503 } 504 return 0 505 } 506 507 func (this *StringIntLinkedEnumer) NextString() string { 508 if this.HasMoreElements() { 509 e := this.entry 510 this.entry = e.link_next 511 return e.key 512 } 513 return "" 514 }