github.com/gogf/gf@v1.16.9/container/gmap/gmap_hash_int_int_map.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). 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/gogf/gf.
     6  
     7  package gmap
     8  
     9  import (
    10  	"github.com/gogf/gf/internal/json"
    11  	"github.com/gogf/gf/util/gconv"
    12  
    13  	"github.com/gogf/gf/internal/empty"
    14  
    15  	"github.com/gogf/gf/internal/rwmutex"
    16  )
    17  
    18  type IntIntMap struct {
    19  	mu   rwmutex.RWMutex
    20  	data map[int]int
    21  }
    22  
    23  // NewIntIntMap returns an empty IntIntMap object.
    24  // The parameter <safe> is used to specify whether using map in concurrent-safety,
    25  // which is false in default.
    26  func NewIntIntMap(safe ...bool) *IntIntMap {
    27  	return &IntIntMap{
    28  		mu:   rwmutex.Create(safe...),
    29  		data: make(map[int]int),
    30  	}
    31  }
    32  
    33  // NewIntIntMapFrom creates and returns a hash map from given map <data>.
    34  // Note that, the param <data> map will be set as the underlying data map(no deep copy),
    35  // there might be some concurrent-safe issues when changing the map outside.
    36  func NewIntIntMapFrom(data map[int]int, safe ...bool) *IntIntMap {
    37  	return &IntIntMap{
    38  		mu:   rwmutex.Create(safe...),
    39  		data: data,
    40  	}
    41  }
    42  
    43  // Iterator iterates the hash map readonly with custom callback function <f>.
    44  // If <f> returns true, then it continues iterating; or false to stop.
    45  func (m *IntIntMap) Iterator(f func(k int, v int) bool) {
    46  	m.mu.RLock()
    47  	defer m.mu.RUnlock()
    48  	for k, v := range m.data {
    49  		if !f(k, v) {
    50  			break
    51  		}
    52  	}
    53  }
    54  
    55  // Clone returns a new hash map with copy of current map data.
    56  func (m *IntIntMap) Clone() *IntIntMap {
    57  	return NewIntIntMapFrom(m.MapCopy(), m.mu.IsSafe())
    58  }
    59  
    60  // Map returns the underlying data map.
    61  // Note that, if it's in concurrent-safe usage, it returns a copy of underlying data,
    62  // or else a pointer to the underlying data.
    63  func (m *IntIntMap) Map() map[int]int {
    64  	m.mu.RLock()
    65  	defer m.mu.RUnlock()
    66  	if !m.mu.IsSafe() {
    67  		return m.data
    68  	}
    69  	data := make(map[int]int, len(m.data))
    70  	for k, v := range m.data {
    71  		data[k] = v
    72  	}
    73  	return data
    74  }
    75  
    76  // MapStrAny returns a copy of the underlying data of the map as map[string]interface{}.
    77  func (m *IntIntMap) MapStrAny() map[string]interface{} {
    78  	m.mu.RLock()
    79  	data := make(map[string]interface{}, len(m.data))
    80  	for k, v := range m.data {
    81  		data[gconv.String(k)] = v
    82  	}
    83  	m.mu.RUnlock()
    84  	return data
    85  }
    86  
    87  // MapCopy returns a copy of the underlying data of the hash map.
    88  func (m *IntIntMap) MapCopy() map[int]int {
    89  	m.mu.RLock()
    90  	defer m.mu.RUnlock()
    91  	data := make(map[int]int, len(m.data))
    92  	for k, v := range m.data {
    93  		data[k] = v
    94  	}
    95  	return data
    96  }
    97  
    98  // FilterEmpty deletes all key-value pair of which the value is empty.
    99  // Values like: 0, nil, false, "", len(slice/map/chan) == 0 are considered empty.
   100  func (m *IntIntMap) FilterEmpty() {
   101  	m.mu.Lock()
   102  	for k, v := range m.data {
   103  		if empty.IsEmpty(v) {
   104  			delete(m.data, k)
   105  		}
   106  	}
   107  	m.mu.Unlock()
   108  }
   109  
   110  // Set sets key-value to the hash map.
   111  func (m *IntIntMap) Set(key int, val int) {
   112  	m.mu.Lock()
   113  	if m.data == nil {
   114  		m.data = make(map[int]int)
   115  	}
   116  	m.data[key] = val
   117  	m.mu.Unlock()
   118  }
   119  
   120  // Sets batch sets key-values to the hash map.
   121  func (m *IntIntMap) Sets(data map[int]int) {
   122  	m.mu.Lock()
   123  	if m.data == nil {
   124  		m.data = data
   125  	} else {
   126  		for k, v := range data {
   127  			m.data[k] = v
   128  		}
   129  	}
   130  	m.mu.Unlock()
   131  }
   132  
   133  // Search searches the map with given <key>.
   134  // Second return parameter <found> is true if key was found, otherwise false.
   135  func (m *IntIntMap) Search(key int) (value int, found bool) {
   136  	m.mu.RLock()
   137  	if m.data != nil {
   138  		value, found = m.data[key]
   139  	}
   140  	m.mu.RUnlock()
   141  	return
   142  }
   143  
   144  // Get returns the value by given <key>.
   145  func (m *IntIntMap) Get(key int) (value int) {
   146  	m.mu.RLock()
   147  	if m.data != nil {
   148  		value, _ = m.data[key]
   149  	}
   150  	m.mu.RUnlock()
   151  	return
   152  }
   153  
   154  // Pop retrieves and deletes an item from the map.
   155  func (m *IntIntMap) Pop() (key, value int) {
   156  	m.mu.Lock()
   157  	defer m.mu.Unlock()
   158  	for key, value = range m.data {
   159  		delete(m.data, key)
   160  		return
   161  	}
   162  	return
   163  }
   164  
   165  // Pops retrieves and deletes <size> items from the map.
   166  // It returns all items if size == -1.
   167  func (m *IntIntMap) Pops(size int) map[int]int {
   168  	m.mu.Lock()
   169  	defer m.mu.Unlock()
   170  	if size > len(m.data) || size == -1 {
   171  		size = len(m.data)
   172  	}
   173  	if size == 0 {
   174  		return nil
   175  	}
   176  	var (
   177  		index  = 0
   178  		newMap = make(map[int]int, size)
   179  	)
   180  	for k, v := range m.data {
   181  		delete(m.data, k)
   182  		newMap[k] = v
   183  		index++
   184  		if index == size {
   185  			break
   186  		}
   187  	}
   188  	return newMap
   189  }
   190  
   191  // doSetWithLockCheck checks whether value of the key exists with mutex.Lock,
   192  // if not exists, set value to the map with given <key>,
   193  // or else just return the existing value.
   194  //
   195  // It returns value with given <key>.
   196  func (m *IntIntMap) doSetWithLockCheck(key int, value int) int {
   197  	m.mu.Lock()
   198  	defer m.mu.Unlock()
   199  	if m.data == nil {
   200  		m.data = make(map[int]int)
   201  	}
   202  	if v, ok := m.data[key]; ok {
   203  		return v
   204  	}
   205  	m.data[key] = value
   206  	return value
   207  }
   208  
   209  // GetOrSet returns the value by key,
   210  // or sets value with given <value> if it does not exist and then returns this value.
   211  func (m *IntIntMap) GetOrSet(key int, value int) int {
   212  	if v, ok := m.Search(key); !ok {
   213  		return m.doSetWithLockCheck(key, value)
   214  	} else {
   215  		return v
   216  	}
   217  }
   218  
   219  // GetOrSetFunc returns the value by key,
   220  // or sets value with returned value of callback function <f> if it does not exist and returns this value.
   221  func (m *IntIntMap) GetOrSetFunc(key int, f func() int) int {
   222  	if v, ok := m.Search(key); !ok {
   223  		return m.doSetWithLockCheck(key, f())
   224  	} else {
   225  		return v
   226  	}
   227  }
   228  
   229  // GetOrSetFuncLock returns the value by key,
   230  // or sets value with returned value of callback function <f> if it does not exist and returns this value.
   231  //
   232  // GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function <f>
   233  // with mutex.Lock of the hash map.
   234  func (m *IntIntMap) GetOrSetFuncLock(key int, f func() int) int {
   235  	if v, ok := m.Search(key); !ok {
   236  		m.mu.Lock()
   237  		defer m.mu.Unlock()
   238  		if m.data == nil {
   239  			m.data = make(map[int]int)
   240  		}
   241  		if v, ok = m.data[key]; ok {
   242  			return v
   243  		}
   244  		v = f()
   245  		m.data[key] = v
   246  		return v
   247  	} else {
   248  		return v
   249  	}
   250  }
   251  
   252  // SetIfNotExist sets <value> to the map if the <key> does not exist, and then returns true.
   253  // It returns false if <key> exists, and <value> would be ignored.
   254  func (m *IntIntMap) SetIfNotExist(key int, value int) bool {
   255  	if !m.Contains(key) {
   256  		m.doSetWithLockCheck(key, value)
   257  		return true
   258  	}
   259  	return false
   260  }
   261  
   262  // SetIfNotExistFunc sets value with return value of callback function <f>, and then returns true.
   263  // It returns false if <key> exists, and <value> would be ignored.
   264  func (m *IntIntMap) SetIfNotExistFunc(key int, f func() int) bool {
   265  	if !m.Contains(key) {
   266  		m.doSetWithLockCheck(key, f())
   267  		return true
   268  	}
   269  	return false
   270  }
   271  
   272  // SetIfNotExistFuncLock sets value with return value of callback function <f>, and then returns true.
   273  // It returns false if <key> exists, and <value> would be ignored.
   274  //
   275  // SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that
   276  // it executes function <f> with mutex.Lock of the hash map.
   277  func (m *IntIntMap) SetIfNotExistFuncLock(key int, f func() int) bool {
   278  	if !m.Contains(key) {
   279  		m.mu.Lock()
   280  		defer m.mu.Unlock()
   281  		if m.data == nil {
   282  			m.data = make(map[int]int)
   283  		}
   284  		if _, ok := m.data[key]; !ok {
   285  			m.data[key] = f()
   286  		}
   287  		return true
   288  	}
   289  	return false
   290  }
   291  
   292  // Removes batch deletes values of the map by keys.
   293  func (m *IntIntMap) Removes(keys []int) {
   294  	m.mu.Lock()
   295  	if m.data != nil {
   296  		for _, key := range keys {
   297  			delete(m.data, key)
   298  		}
   299  	}
   300  	m.mu.Unlock()
   301  }
   302  
   303  // Remove deletes value from map by given <key>, and return this deleted value.
   304  func (m *IntIntMap) Remove(key int) (value int) {
   305  	m.mu.Lock()
   306  	if m.data != nil {
   307  		var ok bool
   308  		if value, ok = m.data[key]; ok {
   309  			delete(m.data, key)
   310  		}
   311  	}
   312  	m.mu.Unlock()
   313  	return
   314  }
   315  
   316  // Keys returns all keys of the map as a slice.
   317  func (m *IntIntMap) Keys() []int {
   318  	m.mu.RLock()
   319  	var (
   320  		keys  = make([]int, len(m.data))
   321  		index = 0
   322  	)
   323  	for key := range m.data {
   324  		keys[index] = key
   325  		index++
   326  	}
   327  	m.mu.RUnlock()
   328  	return keys
   329  }
   330  
   331  // Values returns all values of the map as a slice.
   332  func (m *IntIntMap) Values() []int {
   333  	m.mu.RLock()
   334  	var (
   335  		values = make([]int, len(m.data))
   336  		index  = 0
   337  	)
   338  	for _, value := range m.data {
   339  		values[index] = value
   340  		index++
   341  	}
   342  	m.mu.RUnlock()
   343  	return values
   344  }
   345  
   346  // Contains checks whether a key exists.
   347  // It returns true if the <key> exists, or else false.
   348  func (m *IntIntMap) Contains(key int) bool {
   349  	var ok bool
   350  	m.mu.RLock()
   351  	if m.data != nil {
   352  		_, ok = m.data[key]
   353  	}
   354  	m.mu.RUnlock()
   355  	return ok
   356  }
   357  
   358  // Size returns the size of the map.
   359  func (m *IntIntMap) Size() int {
   360  	m.mu.RLock()
   361  	length := len(m.data)
   362  	m.mu.RUnlock()
   363  	return length
   364  }
   365  
   366  // IsEmpty checks whether the map is empty.
   367  // It returns true if map is empty, or else false.
   368  func (m *IntIntMap) IsEmpty() bool {
   369  	return m.Size() == 0
   370  }
   371  
   372  // Clear deletes all data of the map, it will remake a new underlying data map.
   373  func (m *IntIntMap) Clear() {
   374  	m.mu.Lock()
   375  	m.data = make(map[int]int)
   376  	m.mu.Unlock()
   377  }
   378  
   379  // Replace the data of the map with given <data>.
   380  func (m *IntIntMap) Replace(data map[int]int) {
   381  	m.mu.Lock()
   382  	m.data = data
   383  	m.mu.Unlock()
   384  }
   385  
   386  // LockFunc locks writing with given callback function <f> within RWMutex.Lock.
   387  func (m *IntIntMap) LockFunc(f func(m map[int]int)) {
   388  	m.mu.Lock()
   389  	defer m.mu.Unlock()
   390  	f(m.data)
   391  }
   392  
   393  // RLockFunc locks reading with given callback function <f> within RWMutex.RLock.
   394  func (m *IntIntMap) RLockFunc(f func(m map[int]int)) {
   395  	m.mu.RLock()
   396  	defer m.mu.RUnlock()
   397  	f(m.data)
   398  }
   399  
   400  // Flip exchanges key-value of the map to value-key.
   401  func (m *IntIntMap) Flip() {
   402  	m.mu.Lock()
   403  	defer m.mu.Unlock()
   404  	n := make(map[int]int, len(m.data))
   405  	for k, v := range m.data {
   406  		n[v] = k
   407  	}
   408  	m.data = n
   409  }
   410  
   411  // Merge merges two hash maps.
   412  // The <other> map will be merged into the map <m>.
   413  func (m *IntIntMap) Merge(other *IntIntMap) {
   414  	m.mu.Lock()
   415  	defer m.mu.Unlock()
   416  	if m.data == nil {
   417  		m.data = other.MapCopy()
   418  		return
   419  	}
   420  	if other != m {
   421  		other.mu.RLock()
   422  		defer other.mu.RUnlock()
   423  	}
   424  	for k, v := range other.data {
   425  		m.data[k] = v
   426  	}
   427  }
   428  
   429  // String returns the map as a string.
   430  func (m *IntIntMap) String() string {
   431  	b, _ := m.MarshalJSON()
   432  	return string(b)
   433  }
   434  
   435  // MarshalJSON implements the interface MarshalJSON for json.Marshal.
   436  func (m *IntIntMap) MarshalJSON() ([]byte, error) {
   437  	m.mu.RLock()
   438  	defer m.mu.RUnlock()
   439  	return json.Marshal(m.data)
   440  }
   441  
   442  // UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal.
   443  func (m *IntIntMap) UnmarshalJSON(b []byte) error {
   444  	m.mu.Lock()
   445  	defer m.mu.Unlock()
   446  	if m.data == nil {
   447  		m.data = make(map[int]int)
   448  	}
   449  	if err := json.UnmarshalUseNumber(b, &m.data); err != nil {
   450  		return err
   451  	}
   452  	return nil
   453  }
   454  
   455  // UnmarshalValue is an interface implement which sets any type of value for map.
   456  func (m *IntIntMap) UnmarshalValue(value interface{}) (err error) {
   457  	m.mu.Lock()
   458  	defer m.mu.Unlock()
   459  	if m.data == nil {
   460  		m.data = make(map[int]int)
   461  	}
   462  	switch value.(type) {
   463  	case string, []byte:
   464  		return json.UnmarshalUseNumber(gconv.Bytes(value), &m.data)
   465  	default:
   466  		for k, v := range gconv.Map(value) {
   467  			m.data[gconv.Int(k)] = gconv.Int(v)
   468  		}
   469  	}
   470  	return
   471  }