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