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  }