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