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