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