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