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