github.com/zhongdalu/gf@v1.0.0/g/container/gmap/gmap_link_map.go (about) 1 // Copyright 2017 gf Author(https://github.com/zhongdalu/gf). 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/zhongdalu/gf. 6 7 package gmap 8 9 import ( 10 "encoding/json" 11 12 "github.com/zhongdalu/gf/g/util/gconv" 13 14 "github.com/zhongdalu/gf/g/container/glist" 15 "github.com/zhongdalu/gf/g/container/gvar" 16 "github.com/zhongdalu/gf/g/internal/rwmutex" 17 ) 18 19 type ListMap struct { 20 mu *rwmutex.RWMutex 21 data map[interface{}]*glist.Element 22 list *glist.List 23 } 24 25 type gListMapNode struct { 26 key interface{} 27 value interface{} 28 } 29 30 // NewListMap returns an empty link map. 31 // ListMap is backed by a hash table to store values and doubly-linked list to store ordering. 32 // The parameter <unsafe> used to specify whether using map in un-concurrent-safety, 33 // which is false in default, means concurrent-safe. 34 func NewListMap(unsafe ...bool) *ListMap { 35 return &ListMap{ 36 mu: rwmutex.New(unsafe...), 37 data: make(map[interface{}]*glist.Element), 38 list: glist.New(true), 39 } 40 } 41 42 // NewListMapFrom returns a link map from given map <data>. 43 // Note that, the param <data> map will be set as the underlying data map(no deep copy), 44 // there might be some concurrent-safe issues when changing the map outside. 45 func NewListMapFrom(data map[interface{}]interface{}, unsafe ...bool) *ListMap { 46 m := NewListMap(unsafe...) 47 m.Sets(data) 48 return m 49 } 50 51 // Iterator is alias of IteratorAsc. 52 func (m *ListMap) Iterator(f func(key, value interface{}) bool) { 53 m.IteratorAsc(f) 54 } 55 56 // IteratorAsc iterates the map in ascending order with given callback function <f>. 57 // If <f> returns true, then it continues iterating; or false to stop. 58 func (m *ListMap) IteratorAsc(f func(key interface{}, value interface{}) bool) { 59 m.mu.RLock() 60 defer m.mu.RUnlock() 61 node := (*gListMapNode)(nil) 62 m.list.IteratorAsc(func(e *glist.Element) bool { 63 node = e.Value.(*gListMapNode) 64 return f(node.key, node.value) 65 }) 66 } 67 68 // IteratorDesc iterates the map in descending order with given callback function <f>. 69 // If <f> returns true, then it continues iterating; or false to stop. 70 func (m *ListMap) IteratorDesc(f func(key interface{}, value interface{}) bool) { 71 m.mu.RLock() 72 defer m.mu.RUnlock() 73 node := (*gListMapNode)(nil) 74 m.list.IteratorDesc(func(e *glist.Element) bool { 75 node = e.Value.(*gListMapNode) 76 return f(node.key, node.value) 77 }) 78 } 79 80 // Clone returns a new link map with copy of current map data. 81 func (m *ListMap) Clone(unsafe ...bool) *ListMap { 82 return NewListMapFrom(m.Map(), unsafe...) 83 } 84 85 // Clear deletes all data of the map, it will remake a new underlying data map. 86 func (m *ListMap) Clear() { 87 m.mu.Lock() 88 m.data = make(map[interface{}]*glist.Element) 89 m.list = glist.New(true) 90 m.mu.Unlock() 91 } 92 93 // Map returns a copy of the data of the map. 94 func (m *ListMap) Map() map[interface{}]interface{} { 95 m.mu.RLock() 96 node := (*gListMapNode)(nil) 97 data := make(map[interface{}]interface{}, len(m.data)) 98 m.list.IteratorAsc(func(e *glist.Element) bool { 99 node = e.Value.(*gListMapNode) 100 data[node.key] = node.value 101 return true 102 }) 103 m.mu.RUnlock() 104 return data 105 } 106 107 // Set sets key-value to the map. 108 func (m *ListMap) Set(key interface{}, value interface{}) { 109 m.mu.Lock() 110 if e, ok := m.data[key]; !ok { 111 m.data[key] = m.list.PushBack(&gListMapNode{key, value}) 112 } else { 113 e.Value = &gListMapNode{key, value} 114 } 115 m.mu.Unlock() 116 } 117 118 // Sets batch sets key-values to the map. 119 func (m *ListMap) Sets(data map[interface{}]interface{}) { 120 m.mu.Lock() 121 for key, value := range data { 122 if e, ok := m.data[key]; !ok { 123 m.data[key] = m.list.PushBack(&gListMapNode{key, value}) 124 } else { 125 e.Value = &gListMapNode{key, value} 126 } 127 } 128 m.mu.Unlock() 129 } 130 131 // Search searches the map with given <key>. 132 // Second return parameter <found> is true if key was found, otherwise false. 133 func (m *ListMap) Search(key interface{}) (value interface{}, found bool) { 134 m.mu.RLock() 135 if e, ok := m.data[key]; ok { 136 value = e.Value.(*gListMapNode).value 137 found = ok 138 } 139 m.mu.RUnlock() 140 return 141 } 142 143 // Get returns the value by given <key>. 144 func (m *ListMap) Get(key interface{}) (value interface{}) { 145 m.mu.RLock() 146 if e, ok := m.data[key]; ok { 147 value = e.Value.(*gListMapNode).value 148 } 149 m.mu.RUnlock() 150 return 151 } 152 153 // doSetWithLockCheck checks whether value of the key exists with mutex.Lock, 154 // if not exists, set value to the map with given <key>, 155 // or else just return the existing value. 156 // 157 // When setting value, if <value> is type of <func() interface {}>, 158 // it will be executed with mutex.Lock of the map, 159 // and its return value will be set to the map with <key>. 160 // 161 // It returns value with given <key>. 162 func (m *ListMap) doSetWithLockCheck(key interface{}, value interface{}) interface{} { 163 m.mu.Lock() 164 defer m.mu.Unlock() 165 if e, ok := m.data[key]; ok { 166 return e.Value.(*gListMapNode).value 167 } 168 if f, ok := value.(func() interface{}); ok { 169 value = f() 170 } 171 m.data[key] = m.list.PushBack(&gListMapNode{key, value}) 172 return value 173 } 174 175 // GetOrSet returns the value by key, 176 // or set value with given <value> if not exist and returns this value. 177 func (m *ListMap) GetOrSet(key interface{}, value interface{}) interface{} { 178 if v, ok := m.Search(key); !ok { 179 return m.doSetWithLockCheck(key, value) 180 } else { 181 return v 182 } 183 } 184 185 // GetOrSetFunc returns the value by key, 186 // or sets value with return value of callback function <f> if not exist 187 // and returns this value. 188 func (m *ListMap) GetOrSetFunc(key interface{}, f func() interface{}) interface{} { 189 if v, ok := m.Search(key); !ok { 190 return m.doSetWithLockCheck(key, f()) 191 } else { 192 return v 193 } 194 } 195 196 // GetOrSetFuncLock returns the value by key, 197 // or sets value with return value of callback function <f> if not exist 198 // and returns this value. 199 // 200 // GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function <f> 201 // with mutex.Lock of the map. 202 func (m *ListMap) GetOrSetFuncLock(key interface{}, f func() interface{}) interface{} { 203 if v, ok := m.Search(key); !ok { 204 return m.doSetWithLockCheck(key, f) 205 } else { 206 return v 207 } 208 } 209 210 // GetVar returns a gvar.Var with the value by given <key>. 211 // The returned gvar.Var is un-concurrent safe. 212 func (m *ListMap) GetVar(key interface{}) *gvar.Var { 213 return gvar.New(m.Get(key), true) 214 } 215 216 // GetVarOrSet returns a gvar.Var with result from GetVarOrSet. 217 // The returned gvar.Var is un-concurrent safe. 218 func (m *ListMap) GetVarOrSet(key interface{}, value interface{}) *gvar.Var { 219 return gvar.New(m.GetOrSet(key, value), true) 220 } 221 222 // GetVarOrSetFunc returns a gvar.Var with result from GetOrSetFunc. 223 // The returned gvar.Var is un-concurrent safe. 224 func (m *ListMap) GetVarOrSetFunc(key interface{}, f func() interface{}) *gvar.Var { 225 return gvar.New(m.GetOrSetFunc(key, f), true) 226 } 227 228 // GetVarOrSetFuncLock returns a gvar.Var with result from GetOrSetFuncLock. 229 // The returned gvar.Var is un-concurrent safe. 230 func (m *ListMap) GetVarOrSetFuncLock(key interface{}, f func() interface{}) *gvar.Var { 231 return gvar.New(m.GetOrSetFuncLock(key, f), true) 232 } 233 234 // SetIfNotExist sets <value> to the map if the <key> does not exist, then return true. 235 // It returns false if <key> exists, and <value> would be ignored. 236 func (m *ListMap) SetIfNotExist(key interface{}, value interface{}) bool { 237 if !m.Contains(key) { 238 m.doSetWithLockCheck(key, value) 239 return true 240 } 241 return false 242 } 243 244 // SetIfNotExistFunc sets value with return value of callback function <f>, then return true. 245 // It returns false if <key> exists, and <value> would be ignored. 246 func (m *ListMap) SetIfNotExistFunc(key interface{}, f func() interface{}) bool { 247 if !m.Contains(key) { 248 m.doSetWithLockCheck(key, f()) 249 return true 250 } 251 return false 252 } 253 254 // SetIfNotExistFuncLock sets value with return value of callback function <f>, then return true. 255 // It returns false if <key> exists, and <value> would be ignored. 256 // 257 // SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that 258 // it executes function <f> with mutex.Lock of the map. 259 func (m *ListMap) SetIfNotExistFuncLock(key interface{}, f func() interface{}) bool { 260 if !m.Contains(key) { 261 m.doSetWithLockCheck(key, f) 262 return true 263 } 264 return false 265 } 266 267 // Remove deletes value from map by given <key>, and return this deleted value. 268 func (m *ListMap) Remove(key interface{}) (value interface{}) { 269 m.mu.Lock() 270 if e, ok := m.data[key]; ok { 271 value = e.Value.(*gListMapNode).value 272 delete(m.data, key) 273 m.list.Remove(e) 274 } 275 m.mu.Unlock() 276 return 277 } 278 279 // Removes batch deletes values of the map by keys. 280 func (m *ListMap) Removes(keys []interface{}) { 281 m.mu.Lock() 282 for _, key := range keys { 283 if e, ok := m.data[key]; ok { 284 delete(m.data, key) 285 m.list.Remove(e) 286 } 287 } 288 m.mu.Unlock() 289 } 290 291 // Keys returns all keys of the map as a slice in ascending order. 292 func (m *ListMap) Keys() []interface{} { 293 m.mu.RLock() 294 keys := make([]interface{}, m.list.Len()) 295 index := 0 296 m.list.IteratorAsc(func(e *glist.Element) bool { 297 keys[index] = e.Value.(*gListMapNode).key 298 index++ 299 return true 300 }) 301 m.mu.RUnlock() 302 return keys 303 } 304 305 // Values returns all values of the map as a slice. 306 func (m *ListMap) Values() []interface{} { 307 m.mu.RLock() 308 values := make([]interface{}, m.list.Len()) 309 index := 0 310 m.list.IteratorAsc(func(e *glist.Element) bool { 311 values[index] = e.Value.(*gListMapNode).value 312 index++ 313 return true 314 }) 315 m.mu.RUnlock() 316 return values 317 } 318 319 // Contains checks whether a key exists. 320 // It returns true if the <key> exists, or else false. 321 func (m *ListMap) Contains(key interface{}) (ok bool) { 322 m.mu.RLock() 323 _, ok = m.data[key] 324 m.mu.RUnlock() 325 return 326 } 327 328 // Size returns the size of the map. 329 func (m *ListMap) Size() (size int) { 330 m.mu.RLock() 331 size = len(m.data) 332 m.mu.RUnlock() 333 return 334 } 335 336 // IsEmpty checks whether the map is empty. 337 // It returns true if map is empty, or else false. 338 func (m *ListMap) IsEmpty() bool { 339 return m.Size() == 0 340 } 341 342 // Flip exchanges key-value of the map to value-key. 343 func (m *ListMap) Flip() { 344 data := m.Map() 345 m.Clear() 346 for key, value := range data { 347 m.Set(value, key) 348 } 349 } 350 351 // Merge merges two link maps. 352 // The <other> map will be merged into the map <m>. 353 func (m *ListMap) Merge(other *ListMap) { 354 m.mu.Lock() 355 defer m.mu.Unlock() 356 if other != m { 357 other.mu.RLock() 358 defer other.mu.RUnlock() 359 } 360 node := (*gListMapNode)(nil) 361 other.list.IteratorAsc(func(e *glist.Element) bool { 362 node = e.Value.(*gListMapNode) 363 if e, ok := m.data[node.key]; !ok { 364 m.data[node.key] = m.list.PushBack(&gListMapNode{node.key, node.value}) 365 } else { 366 e.Value = &gListMapNode{node.key, node.value} 367 } 368 return true 369 }) 370 } 371 372 // MarshalJSON implements the interface MarshalJSON for json.Marshal. 373 func (m *ListMap) MarshalJSON() ([]byte, error) { 374 return json.Marshal(gconv.Map(m.Map())) 375 }