github.com/whatap/golib@v0.0.22/util/hmap/LinkedMap.go (about) 1 package hmap 2 3 import ( 4 "bytes" 5 "sort" 6 "sync" 7 ) 8 9 type LinkedMap struct { 10 table []*LinkedEntry 11 header *LinkedEntry 12 count int 13 threshold int 14 loadFactor float32 15 lock sync.Mutex 16 max int 17 } 18 19 func NewLinkedMapDefault() *LinkedMap { 20 return NewLinkedMap(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR) 21 } 22 23 func NewLinkedMap(initCapacity int, loadFactor float32) *LinkedMap { 24 25 this := new(LinkedMap) 26 this.loadFactor = float32(loadFactor) 27 this.table = make([]*LinkedEntry, initCapacity) 28 this.header = &LinkedEntry{} 29 this.header.link_next = this.header 30 this.header.link_prev = this.header 31 this.threshold = int(float32(initCapacity) * loadFactor) 32 return this 33 } 34 35 func (this *LinkedMap) Size() int { 36 return this.count 37 } 38 39 func (this *LinkedMap) KeyArray() []LinkedKey { 40 this.lock.Lock() 41 defer this.lock.Unlock() 42 43 _keys := make([]LinkedKey, this.Size()) 44 en := this.Keys() 45 for i := 0; i < len(_keys); i++ { 46 _keys[i] = en.NextElement().(LinkedKey) 47 } 48 return _keys 49 } 50 51 type EnumerImpl struct { 52 parent *LinkedMap 53 entry *LinkedEntry 54 rtype int 55 } 56 57 func (this *EnumerImpl) HasMoreElements() bool { 58 return this.entry != nil && this.parent.header != this.entry 59 } 60 61 func (this *EnumerImpl) NextElement() interface{} { 62 if this.HasMoreElements() { 63 e := this.entry 64 this.entry = e.link_next 65 switch this.rtype { 66 case 1: 67 return e.GetKey() 68 case 2: 69 return e.GetValue() 70 case 3: 71 return e 72 } 73 } 74 return "" 75 } 76 func (this *LinkedMap) Keys() Enumeration { 77 return &EnumerImpl{parent: this, entry: this.header.link_next, rtype: 1} 78 } 79 func (this *LinkedMap) Values() Enumeration { 80 return &EnumerImpl{parent: this, entry: this.header.link_next, rtype: 2} 81 } 82 func (this *LinkedMap) Entries() Enumeration { 83 return &EnumerImpl{parent: this, entry: this.header.link_next, rtype: 3} 84 } 85 86 func (this *LinkedMap) ContainsKey(key LinkedKey) bool { 87 this.lock.Lock() 88 defer this.lock.Unlock() 89 90 tab := this.table 91 index := this.hash(key) % uint(len(tab)) 92 for e := tab[index]; e != nil; e = e.hash_next { 93 if e.key.Equals(key) { 94 return true 95 } 96 } 97 return false 98 99 } 100 func (this *LinkedMap) Get(key LinkedKey) interface{} { 101 this.lock.Lock() 102 defer this.lock.Unlock() 103 104 tab := this.table 105 index := this.hash(key) % uint(len(tab)) 106 for e := tab[index]; e != nil; e = e.hash_next { 107 if e.key.Equals(key) { 108 return e.value 109 } 110 } 111 return nil 112 } 113 func (this *LinkedMap) GetFirstKey() LinkedKey { 114 this.lock.Lock() 115 defer this.lock.Unlock() 116 117 return this.header.link_next.key 118 } 119 120 func (this *LinkedMap) GetLastKey() LinkedKey { 121 this.lock.Lock() 122 defer this.lock.Unlock() 123 return this.header.link_prev.key 124 } 125 126 func (this *LinkedMap) GetFirstValue() interface{} { 127 this.lock.Lock() 128 defer this.lock.Unlock() 129 130 return this.header.link_next.value 131 } 132 133 func (this *LinkedMap) GetLastValue() interface{} { 134 this.lock.Lock() 135 defer this.lock.Unlock() 136 137 return this.header.link_prev.value 138 } 139 func (this *LinkedMap) hash(key LinkedKey) uint { 140 return key.Hash() 141 } 142 143 func (this *LinkedMap) rehash() { 144 oldCapacity := len(this.table) 145 oldMap := this.table 146 newCapacity := oldCapacity*2 + 1 147 newMap := make([]*LinkedEntry, newCapacity) 148 this.threshold = int(float32(newCapacity) * this.loadFactor) 149 this.table = newMap 150 for i := oldCapacity; i > 0; i-- { 151 for old := oldMap[i-1]; old != nil; { 152 e := old 153 old = old.hash_next 154 index := uint(e.keyHash % uint(newCapacity)) 155 e.hash_next = newMap[index] 156 newMap[index] = e 157 } 158 } 159 } 160 161 func (this *LinkedMap) SetMax(max int) *LinkedMap { 162 this.max = max 163 return this 164 } 165 func (this *LinkedMap) Put(key LinkedKey, value interface{}) interface{} { 166 this.lock.Lock() 167 defer this.lock.Unlock() 168 return this.put(key, value, PUT_LAST) 169 } 170 func (this *LinkedMap) PutLast(key LinkedKey, value interface{}) interface{} { 171 this.lock.Lock() 172 defer this.lock.Unlock() 173 return this.put(key, value, PUT_FORCE_LAST) 174 } 175 func (this *LinkedMap) PutFirst(key LinkedKey, value interface{}) interface{} { 176 this.lock.Lock() 177 defer this.lock.Unlock() 178 return this.put(key, value, PUT_FORCE_FIRST) 179 } 180 func (this *LinkedMap) put(key LinkedKey, value interface{}, m PUT_MODE) interface{} { 181 182 tab := this.table 183 keyHash := this.hash(key) 184 index := keyHash % uint(len(tab)) 185 for e := tab[index]; e != nil; e = e.hash_next { 186 if e.key.Equals(key) { 187 old := e.value 188 e.value = value 189 switch m { 190 case PUT_FORCE_FIRST: 191 if this.header.link_next != e { 192 this.unchain(e) 193 this.chain(this.header, this.header.link_next, e) 194 } 195 case PUT_FORCE_LAST: 196 if this.header.link_prev != e { 197 this.unchain(e) 198 this.chain(this.header.link_prev, this.header, e) 199 } 200 } 201 return old 202 } 203 } 204 if this.max > 0 { 205 switch m { 206 case PUT_FORCE_FIRST, PUT_FIRST: 207 for this.count >= this.max { 208 k := this.header.link_prev.key 209 this.remove(k) 210 } 211 case PUT_FORCE_LAST, PUT_LAST: 212 for this.count >= this.max { 213 // removeFirst(); 214 k := this.header.link_next.key 215 this.remove(k) 216 } 217 break 218 } 219 } 220 if this.count >= this.threshold { 221 this.rehash() 222 tab = this.table 223 index = keyHash % uint(len(tab)) 224 } 225 e := &LinkedEntry{key: key, keyHash: keyHash, value: value, hash_next: tab[index]} 226 tab[index] = e 227 switch m { 228 case PUT_FORCE_FIRST, PUT_FIRST: 229 this.chain(this.header, this.header.link_next, e) 230 case PUT_FORCE_LAST, PUT_LAST: 231 this.chain(this.header.link_prev, this.header, e) 232 } 233 this.count++ 234 return "" 235 } 236 237 func (this *LinkedMap) Remove(key LinkedKey) interface{} { 238 this.lock.Lock() 239 defer this.lock.Unlock() 240 241 return this.remove(key) 242 } 243 func (this *LinkedMap) RemoveFirst() interface{} { 244 if this.IsEmpty() { 245 return 0 246 } 247 this.lock.Lock() 248 defer this.lock.Unlock() 249 return this.remove(this.header.link_next.key) 250 } 251 252 func (this *LinkedMap) RemoveLast() interface{} { 253 if this.IsEmpty() { 254 return 0 255 } 256 this.lock.Lock() 257 defer this.lock.Unlock() 258 return this.remove(this.header.link_prev.key) 259 } 260 261 func (this *LinkedMap) remove(key LinkedKey) interface{} { 262 263 tab := this.table 264 index := this.hash(key) % uint(len(tab)) 265 e := tab[index] 266 var prev *LinkedEntry = nil 267 for e != nil { 268 if e.key.Equals(key) { 269 if prev != nil { 270 prev.hash_next = e.hash_next 271 } else { 272 tab[index] = e.hash_next 273 } 274 this.count-- 275 oldValue := e.value 276 e.value = nil 277 // 278 this.unchain(e) 279 return oldValue 280 } 281 prev = e 282 e = e.hash_next 283 } 284 return nil 285 } 286 287 func (this *LinkedMap) IsEmpty() bool { 288 return this.count == 0 289 } 290 func (this *LinkedMap) IsFull() bool { 291 return this.max > 0 && this.max <= this.count 292 } 293 294 func (this *LinkedMap) Clear() { 295 this.lock.Lock() 296 defer this.lock.Unlock() 297 this.clear() 298 } 299 func (this *LinkedMap) clear() { 300 tab := this.table 301 for index := len(tab) - 1; index >= 0; index-- { 302 tab[index] = nil 303 } 304 this.header.link_next = this.header 305 this.header.link_prev = this.header 306 this.count = 0 307 } 308 309 func (this *LinkedMap) chain(link_prev *LinkedEntry, link_next *LinkedEntry, e *LinkedEntry) { 310 e.link_prev = link_prev 311 e.link_next = link_next 312 link_prev.link_next = e 313 link_next.link_prev = e 314 } 315 316 func (this *LinkedMap) unchain(e *LinkedEntry) { 317 e.link_prev.link_next = e.link_next 318 e.link_next.link_prev = e.link_prev 319 e.link_prev = nil 320 e.link_next = nil 321 } 322 323 type mapSortable struct { 324 compare func(a, b LinkedKey) bool 325 data []*LinkedEntry 326 } 327 328 func (this mapSortable) Len() int { 329 return len(this.data) 330 } 331 func (this mapSortable) Less(i, j int) bool { 332 return this.compare(this.data[i].GetKey(), this.data[j].GetKey()) 333 } 334 335 func (this mapSortable) Swap(i, j int) { 336 this.data[i], this.data[j] = this.data[j], this.data[i] 337 } 338 339 func (this *LinkedMap) Sort(c func(k1, k2 LinkedKey) bool) { 340 this.lock.Lock() 341 defer this.lock.Unlock() 342 343 sz := this.Size() 344 list := make([]*LinkedEntry, sz) 345 en := this.Entries() 346 for i := 0; i < sz; i++ { 347 list[i] = en.NextElement().(*LinkedEntry) 348 } 349 sort.Sort(mapSortable{compare: c, data: list}) 350 351 this.clear() 352 for i := 0; i < sz; i++ { 353 this.put(list[i].GetKey(), list[i].GetValue(), PUT_LAST) 354 } 355 } 356 357 func (this *LinkedMap) ToString() string { 358 this.lock.Lock() 359 defer this.lock.Unlock() 360 361 var buffer bytes.Buffer 362 x := this.Entries() 363 buffer.WriteString("{") 364 for i := 0; x.HasMoreElements(); i++ { 365 if i > 0 { 366 buffer.WriteString(", ") 367 } 368 e := x.NextElement().(*LinkedEntry) 369 buffer.WriteString(e.ToString()) 370 } 371 buffer.WriteString("}") 372 return buffer.String() 373 }