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