github.com/gogf/gf@v1.16.9/container/gmap/gmap_hash_int_str_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 12 "github.com/gogf/gf/internal/empty" 13 14 "github.com/gogf/gf/internal/rwmutex" 15 "github.com/gogf/gf/util/gconv" 16 ) 17 18 type IntStrMap struct { 19 mu rwmutex.RWMutex 20 data map[int]string 21 } 22 23 // NewIntStrMap returns an empty IntStrMap object. 24 // The parameter <safe> is used to specify whether using map in concurrent-safety, 25 // which is false in default. 26 func NewIntStrMap(safe ...bool) *IntStrMap { 27 return &IntStrMap{ 28 mu: rwmutex.Create(safe...), 29 data: make(map[int]string), 30 } 31 } 32 33 // NewIntStrMapFrom 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 NewIntStrMapFrom(data map[int]string, safe ...bool) *IntStrMap { 37 return &IntStrMap{ 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 *IntStrMap) Iterator(f func(k int, v string) 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 *IntStrMap) Clone() *IntStrMap { 57 return NewIntStrMapFrom(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 *IntStrMap) Map() map[int]string { 64 m.mu.RLock() 65 defer m.mu.RUnlock() 66 if !m.mu.IsSafe() { 67 return m.data 68 } 69 data := make(map[int]string, 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 *IntStrMap) 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 *IntStrMap) MapCopy() map[int]string { 89 m.mu.RLock() 90 defer m.mu.RUnlock() 91 data := make(map[int]string, 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 *IntStrMap) 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 *IntStrMap) Set(key int, val string) { 112 m.mu.Lock() 113 if m.data == nil { 114 m.data = make(map[int]string) 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 *IntStrMap) Sets(data map[int]string) { 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 *IntStrMap) Search(key int) (value string, 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 *IntStrMap) Get(key int) (value string) { 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 *IntStrMap) Pop() (key int, value string) { 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 *IntStrMap) Pops(size int) map[int]string { 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]string, 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 *IntStrMap) doSetWithLockCheck(key int, value string) string { 197 m.mu.Lock() 198 defer m.mu.Unlock() 199 if m.data == nil { 200 m.data = make(map[int]string) 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 *IntStrMap) GetOrSet(key int, value string) string { 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 *IntStrMap) GetOrSetFunc(key int, f func() string) string { 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 *IntStrMap) GetOrSetFuncLock(key int, f func() string) string { 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]string) 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 *IntStrMap) SetIfNotExist(key int, value string) 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 *IntStrMap) SetIfNotExistFunc(key int, f func() string) 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 *IntStrMap) SetIfNotExistFuncLock(key int, f func() string) 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]string) 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 *IntStrMap) 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 *IntStrMap) Remove(key int) (value string) { 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 *IntStrMap) 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 *IntStrMap) Values() []string { 333 m.mu.RLock() 334 var ( 335 values = make([]string, 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 *IntStrMap) 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 *IntStrMap) 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 *IntStrMap) 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 *IntStrMap) Clear() { 374 m.mu.Lock() 375 m.data = make(map[int]string) 376 m.mu.Unlock() 377 } 378 379 // Replace the data of the map with given <data>. 380 func (m *IntStrMap) Replace(data map[int]string) { 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 *IntStrMap) LockFunc(f func(m map[int]string)) { 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 *IntStrMap) RLockFunc(f func(m map[int]string)) { 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 *IntStrMap) Flip() { 402 m.mu.Lock() 403 defer m.mu.Unlock() 404 n := make(map[int]string, len(m.data)) 405 for k, v := range m.data { 406 n[gconv.Int(v)] = gconv.String(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 *IntStrMap) Merge(other *IntStrMap) { 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 *IntStrMap) String() string { 431 b, _ := m.MarshalJSON() 432 return string(b) 433 } 434 435 // MarshalJSON implements the interface MarshalJSON for json.Marshal. 436 func (m *IntStrMap) 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 *IntStrMap) UnmarshalJSON(b []byte) error { 444 m.mu.Lock() 445 defer m.mu.Unlock() 446 if m.data == nil { 447 m.data = make(map[int]string) 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 *IntStrMap) 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]string) 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.String(v) 468 } 469 } 470 return 471 }