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