github.com/gogf/gf@v1.16.9/container/gmap/gmap_hash_int_int_map.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with gm file, 5 // You can obtain one at https://github.com/gogf/gf. 6 7 package gmap 8 9 import ( 10 "github.com/gogf/gf/internal/json" 11 "github.com/gogf/gf/util/gconv" 12 13 "github.com/gogf/gf/internal/empty" 14 15 "github.com/gogf/gf/internal/rwmutex" 16 ) 17 18 type IntIntMap struct { 19 mu rwmutex.RWMutex 20 data map[int]int 21 } 22 23 // NewIntIntMap returns an empty IntIntMap object. 24 // The parameter <safe> is used to specify whether using map in concurrent-safety, 25 // which is false in default. 26 func NewIntIntMap(safe ...bool) *IntIntMap { 27 return &IntIntMap{ 28 mu: rwmutex.Create(safe...), 29 data: make(map[int]int), 30 } 31 } 32 33 // NewIntIntMapFrom creates and returns a hash map from given map <data>. 34 // Note that, the param <data> map will be set as the underlying data map(no deep copy), 35 // there might be some concurrent-safe issues when changing the map outside. 36 func NewIntIntMapFrom(data map[int]int, safe ...bool) *IntIntMap { 37 return &IntIntMap{ 38 mu: rwmutex.Create(safe...), 39 data: data, 40 } 41 } 42 43 // Iterator iterates the hash map readonly with custom callback function <f>. 44 // If <f> returns true, then it continues iterating; or false to stop. 45 func (m *IntIntMap) Iterator(f func(k int, v int) bool) { 46 m.mu.RLock() 47 defer m.mu.RUnlock() 48 for k, v := range m.data { 49 if !f(k, v) { 50 break 51 } 52 } 53 } 54 55 // Clone returns a new hash map with copy of current map data. 56 func (m *IntIntMap) Clone() *IntIntMap { 57 return NewIntIntMapFrom(m.MapCopy(), m.mu.IsSafe()) 58 } 59 60 // Map returns the underlying data map. 61 // Note that, if it's in concurrent-safe usage, it returns a copy of underlying data, 62 // or else a pointer to the underlying data. 63 func (m *IntIntMap) Map() map[int]int { 64 m.mu.RLock() 65 defer m.mu.RUnlock() 66 if !m.mu.IsSafe() { 67 return m.data 68 } 69 data := make(map[int]int, len(m.data)) 70 for k, v := range m.data { 71 data[k] = v 72 } 73 return data 74 } 75 76 // MapStrAny returns a copy of the underlying data of the map as map[string]interface{}. 77 func (m *IntIntMap) MapStrAny() map[string]interface{} { 78 m.mu.RLock() 79 data := make(map[string]interface{}, len(m.data)) 80 for k, v := range m.data { 81 data[gconv.String(k)] = v 82 } 83 m.mu.RUnlock() 84 return data 85 } 86 87 // MapCopy returns a copy of the underlying data of the hash map. 88 func (m *IntIntMap) MapCopy() map[int]int { 89 m.mu.RLock() 90 defer m.mu.RUnlock() 91 data := make(map[int]int, len(m.data)) 92 for k, v := range m.data { 93 data[k] = v 94 } 95 return data 96 } 97 98 // FilterEmpty deletes all key-value pair of which the value is empty. 99 // Values like: 0, nil, false, "", len(slice/map/chan) == 0 are considered empty. 100 func (m *IntIntMap) FilterEmpty() { 101 m.mu.Lock() 102 for k, v := range m.data { 103 if empty.IsEmpty(v) { 104 delete(m.data, k) 105 } 106 } 107 m.mu.Unlock() 108 } 109 110 // Set sets key-value to the hash map. 111 func (m *IntIntMap) Set(key int, val int) { 112 m.mu.Lock() 113 if m.data == nil { 114 m.data = make(map[int]int) 115 } 116 m.data[key] = val 117 m.mu.Unlock() 118 } 119 120 // Sets batch sets key-values to the hash map. 121 func (m *IntIntMap) Sets(data map[int]int) { 122 m.mu.Lock() 123 if m.data == nil { 124 m.data = data 125 } else { 126 for k, v := range data { 127 m.data[k] = v 128 } 129 } 130 m.mu.Unlock() 131 } 132 133 // Search searches the map with given <key>. 134 // Second return parameter <found> is true if key was found, otherwise false. 135 func (m *IntIntMap) Search(key int) (value int, found bool) { 136 m.mu.RLock() 137 if m.data != nil { 138 value, found = m.data[key] 139 } 140 m.mu.RUnlock() 141 return 142 } 143 144 // Get returns the value by given <key>. 145 func (m *IntIntMap) Get(key int) (value int) { 146 m.mu.RLock() 147 if m.data != nil { 148 value, _ = m.data[key] 149 } 150 m.mu.RUnlock() 151 return 152 } 153 154 // Pop retrieves and deletes an item from the map. 155 func (m *IntIntMap) Pop() (key, value int) { 156 m.mu.Lock() 157 defer m.mu.Unlock() 158 for key, value = range m.data { 159 delete(m.data, key) 160 return 161 } 162 return 163 } 164 165 // Pops retrieves and deletes <size> items from the map. 166 // It returns all items if size == -1. 167 func (m *IntIntMap) Pops(size int) map[int]int { 168 m.mu.Lock() 169 defer m.mu.Unlock() 170 if size > len(m.data) || size == -1 { 171 size = len(m.data) 172 } 173 if size == 0 { 174 return nil 175 } 176 var ( 177 index = 0 178 newMap = make(map[int]int, size) 179 ) 180 for k, v := range m.data { 181 delete(m.data, k) 182 newMap[k] = v 183 index++ 184 if index == size { 185 break 186 } 187 } 188 return newMap 189 } 190 191 // doSetWithLockCheck checks whether value of the key exists with mutex.Lock, 192 // if not exists, set value to the map with given <key>, 193 // or else just return the existing value. 194 // 195 // It returns value with given <key>. 196 func (m *IntIntMap) doSetWithLockCheck(key int, value int) int { 197 m.mu.Lock() 198 defer m.mu.Unlock() 199 if m.data == nil { 200 m.data = make(map[int]int) 201 } 202 if v, ok := m.data[key]; ok { 203 return v 204 } 205 m.data[key] = value 206 return value 207 } 208 209 // GetOrSet returns the value by key, 210 // or sets value with given <value> if it does not exist and then returns this value. 211 func (m *IntIntMap) GetOrSet(key int, value int) int { 212 if v, ok := m.Search(key); !ok { 213 return m.doSetWithLockCheck(key, value) 214 } else { 215 return v 216 } 217 } 218 219 // GetOrSetFunc returns the value by key, 220 // or sets value with returned value of callback function <f> if it does not exist and returns this value. 221 func (m *IntIntMap) GetOrSetFunc(key int, f func() int) int { 222 if v, ok := m.Search(key); !ok { 223 return m.doSetWithLockCheck(key, f()) 224 } else { 225 return v 226 } 227 } 228 229 // GetOrSetFuncLock returns the value by key, 230 // or sets value with returned value of callback function <f> if it does not exist and returns this value. 231 // 232 // GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function <f> 233 // with mutex.Lock of the hash map. 234 func (m *IntIntMap) GetOrSetFuncLock(key int, f func() int) int { 235 if v, ok := m.Search(key); !ok { 236 m.mu.Lock() 237 defer m.mu.Unlock() 238 if m.data == nil { 239 m.data = make(map[int]int) 240 } 241 if v, ok = m.data[key]; ok { 242 return v 243 } 244 v = f() 245 m.data[key] = v 246 return v 247 } else { 248 return v 249 } 250 } 251 252 // SetIfNotExist sets <value> to the map if the <key> does not exist, and then returns true. 253 // It returns false if <key> exists, and <value> would be ignored. 254 func (m *IntIntMap) SetIfNotExist(key int, value int) bool { 255 if !m.Contains(key) { 256 m.doSetWithLockCheck(key, value) 257 return true 258 } 259 return false 260 } 261 262 // SetIfNotExistFunc sets value with return value of callback function <f>, and then returns true. 263 // It returns false if <key> exists, and <value> would be ignored. 264 func (m *IntIntMap) SetIfNotExistFunc(key int, f func() int) bool { 265 if !m.Contains(key) { 266 m.doSetWithLockCheck(key, f()) 267 return true 268 } 269 return false 270 } 271 272 // SetIfNotExistFuncLock sets value with return value of callback function <f>, and then returns true. 273 // It returns false if <key> exists, and <value> would be ignored. 274 // 275 // SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that 276 // it executes function <f> with mutex.Lock of the hash map. 277 func (m *IntIntMap) SetIfNotExistFuncLock(key int, f func() int) bool { 278 if !m.Contains(key) { 279 m.mu.Lock() 280 defer m.mu.Unlock() 281 if m.data == nil { 282 m.data = make(map[int]int) 283 } 284 if _, ok := m.data[key]; !ok { 285 m.data[key] = f() 286 } 287 return true 288 } 289 return false 290 } 291 292 // Removes batch deletes values of the map by keys. 293 func (m *IntIntMap) Removes(keys []int) { 294 m.mu.Lock() 295 if m.data != nil { 296 for _, key := range keys { 297 delete(m.data, key) 298 } 299 } 300 m.mu.Unlock() 301 } 302 303 // Remove deletes value from map by given <key>, and return this deleted value. 304 func (m *IntIntMap) Remove(key int) (value int) { 305 m.mu.Lock() 306 if m.data != nil { 307 var ok bool 308 if value, ok = m.data[key]; ok { 309 delete(m.data, key) 310 } 311 } 312 m.mu.Unlock() 313 return 314 } 315 316 // Keys returns all keys of the map as a slice. 317 func (m *IntIntMap) Keys() []int { 318 m.mu.RLock() 319 var ( 320 keys = make([]int, len(m.data)) 321 index = 0 322 ) 323 for key := range m.data { 324 keys[index] = key 325 index++ 326 } 327 m.mu.RUnlock() 328 return keys 329 } 330 331 // Values returns all values of the map as a slice. 332 func (m *IntIntMap) Values() []int { 333 m.mu.RLock() 334 var ( 335 values = make([]int, len(m.data)) 336 index = 0 337 ) 338 for _, value := range m.data { 339 values[index] = value 340 index++ 341 } 342 m.mu.RUnlock() 343 return values 344 } 345 346 // Contains checks whether a key exists. 347 // It returns true if the <key> exists, or else false. 348 func (m *IntIntMap) Contains(key int) bool { 349 var ok bool 350 m.mu.RLock() 351 if m.data != nil { 352 _, ok = m.data[key] 353 } 354 m.mu.RUnlock() 355 return ok 356 } 357 358 // Size returns the size of the map. 359 func (m *IntIntMap) Size() int { 360 m.mu.RLock() 361 length := len(m.data) 362 m.mu.RUnlock() 363 return length 364 } 365 366 // IsEmpty checks whether the map is empty. 367 // It returns true if map is empty, or else false. 368 func (m *IntIntMap) IsEmpty() bool { 369 return m.Size() == 0 370 } 371 372 // Clear deletes all data of the map, it will remake a new underlying data map. 373 func (m *IntIntMap) Clear() { 374 m.mu.Lock() 375 m.data = make(map[int]int) 376 m.mu.Unlock() 377 } 378 379 // Replace the data of the map with given <data>. 380 func (m *IntIntMap) Replace(data map[int]int) { 381 m.mu.Lock() 382 m.data = data 383 m.mu.Unlock() 384 } 385 386 // LockFunc locks writing with given callback function <f> within RWMutex.Lock. 387 func (m *IntIntMap) LockFunc(f func(m map[int]int)) { 388 m.mu.Lock() 389 defer m.mu.Unlock() 390 f(m.data) 391 } 392 393 // RLockFunc locks reading with given callback function <f> within RWMutex.RLock. 394 func (m *IntIntMap) RLockFunc(f func(m map[int]int)) { 395 m.mu.RLock() 396 defer m.mu.RUnlock() 397 f(m.data) 398 } 399 400 // Flip exchanges key-value of the map to value-key. 401 func (m *IntIntMap) Flip() { 402 m.mu.Lock() 403 defer m.mu.Unlock() 404 n := make(map[int]int, len(m.data)) 405 for k, v := range m.data { 406 n[v] = k 407 } 408 m.data = n 409 } 410 411 // Merge merges two hash maps. 412 // The <other> map will be merged into the map <m>. 413 func (m *IntIntMap) Merge(other *IntIntMap) { 414 m.mu.Lock() 415 defer m.mu.Unlock() 416 if m.data == nil { 417 m.data = other.MapCopy() 418 return 419 } 420 if other != m { 421 other.mu.RLock() 422 defer other.mu.RUnlock() 423 } 424 for k, v := range other.data { 425 m.data[k] = v 426 } 427 } 428 429 // String returns the map as a string. 430 func (m *IntIntMap) String() string { 431 b, _ := m.MarshalJSON() 432 return string(b) 433 } 434 435 // MarshalJSON implements the interface MarshalJSON for json.Marshal. 436 func (m *IntIntMap) MarshalJSON() ([]byte, error) { 437 m.mu.RLock() 438 defer m.mu.RUnlock() 439 return json.Marshal(m.data) 440 } 441 442 // UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal. 443 func (m *IntIntMap) UnmarshalJSON(b []byte) error { 444 m.mu.Lock() 445 defer m.mu.Unlock() 446 if m.data == nil { 447 m.data = make(map[int]int) 448 } 449 if err := json.UnmarshalUseNumber(b, &m.data); err != nil { 450 return err 451 } 452 return nil 453 } 454 455 // UnmarshalValue is an interface implement which sets any type of value for map. 456 func (m *IntIntMap) UnmarshalValue(value interface{}) (err error) { 457 m.mu.Lock() 458 defer m.mu.Unlock() 459 if m.data == nil { 460 m.data = make(map[int]int) 461 } 462 switch value.(type) { 463 case string, []byte: 464 return json.UnmarshalUseNumber(gconv.Bytes(value), &m.data) 465 default: 466 for k, v := range gconv.Map(value) { 467 m.data[gconv.Int(k)] = gconv.Int(v) 468 } 469 } 470 return 471 }