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