github.com/gogf/gf@v1.16.9/container/gmap/gmap_list_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  
    12  	"github.com/gogf/gf/internal/empty"
    13  
    14  	"github.com/gogf/gf/util/gconv"
    15  
    16  	"github.com/gogf/gf/container/glist"
    17  	"github.com/gogf/gf/container/gvar"
    18  	"github.com/gogf/gf/internal/rwmutex"
    19  )
    20  
    21  type ListMap struct {
    22  	mu   rwmutex.RWMutex
    23  	data map[interface{}]*glist.Element
    24  	list *glist.List
    25  }
    26  
    27  type gListMapNode struct {
    28  	key   interface{}
    29  	value interface{}
    30  }
    31  
    32  // NewListMap returns an empty link map.
    33  // ListMap is backed by a hash table to store values and doubly-linked list to store ordering.
    34  // The parameter <safe> is used to specify whether using map in concurrent-safety,
    35  // which is false in default.
    36  func NewListMap(safe ...bool) *ListMap {
    37  	return &ListMap{
    38  		mu:   rwmutex.Create(safe...),
    39  		data: make(map[interface{}]*glist.Element),
    40  		list: glist.New(),
    41  	}
    42  }
    43  
    44  // NewListMapFrom returns a link map from given map <data>.
    45  // Note that, the param <data> map will be set as the underlying data map(no deep copy),
    46  // there might be some concurrent-safe issues when changing the map outside.
    47  func NewListMapFrom(data map[interface{}]interface{}, safe ...bool) *ListMap {
    48  	m := NewListMap(safe...)
    49  	m.Sets(data)
    50  	return m
    51  }
    52  
    53  // Iterator is alias of IteratorAsc.
    54  func (m *ListMap) Iterator(f func(key, value interface{}) bool) {
    55  	m.IteratorAsc(f)
    56  }
    57  
    58  // IteratorAsc iterates the map readonly in ascending order with given callback function <f>.
    59  // If <f> returns true, then it continues iterating; or false to stop.
    60  func (m *ListMap) IteratorAsc(f func(key interface{}, value interface{}) bool) {
    61  	m.mu.RLock()
    62  	defer m.mu.RUnlock()
    63  	if m.list != nil {
    64  		node := (*gListMapNode)(nil)
    65  		m.list.IteratorAsc(func(e *glist.Element) bool {
    66  			node = e.Value.(*gListMapNode)
    67  			return f(node.key, node.value)
    68  		})
    69  	}
    70  }
    71  
    72  // IteratorDesc iterates the map readonly in descending order with given callback function <f>.
    73  // If <f> returns true, then it continues iterating; or false to stop.
    74  func (m *ListMap) IteratorDesc(f func(key interface{}, value interface{}) bool) {
    75  	m.mu.RLock()
    76  	defer m.mu.RUnlock()
    77  	if m.list != nil {
    78  		node := (*gListMapNode)(nil)
    79  		m.list.IteratorDesc(func(e *glist.Element) bool {
    80  			node = e.Value.(*gListMapNode)
    81  			return f(node.key, node.value)
    82  		})
    83  	}
    84  }
    85  
    86  // Clone returns a new link map with copy of current map data.
    87  func (m *ListMap) Clone(safe ...bool) *ListMap {
    88  	return NewListMapFrom(m.Map(), safe...)
    89  }
    90  
    91  // Clear deletes all data of the map, it will remake a new underlying data map.
    92  func (m *ListMap) Clear() {
    93  	m.mu.Lock()
    94  	m.data = make(map[interface{}]*glist.Element)
    95  	m.list = glist.New()
    96  	m.mu.Unlock()
    97  }
    98  
    99  // Replace the data of the map with given <data>.
   100  func (m *ListMap) Replace(data map[interface{}]interface{}) {
   101  	m.mu.Lock()
   102  	m.data = make(map[interface{}]*glist.Element)
   103  	m.list = glist.New()
   104  	for key, value := range data {
   105  		if e, ok := m.data[key]; !ok {
   106  			m.data[key] = m.list.PushBack(&gListMapNode{key, value})
   107  		} else {
   108  			e.Value = &gListMapNode{key, value}
   109  		}
   110  	}
   111  	m.mu.Unlock()
   112  }
   113  
   114  // Map returns a copy of the underlying data of the map.
   115  func (m *ListMap) Map() map[interface{}]interface{} {
   116  	m.mu.RLock()
   117  	var node *gListMapNode
   118  	var data map[interface{}]interface{}
   119  	if m.list != nil {
   120  		data = make(map[interface{}]interface{}, len(m.data))
   121  		m.list.IteratorAsc(func(e *glist.Element) bool {
   122  			node = e.Value.(*gListMapNode)
   123  			data[node.key] = node.value
   124  			return true
   125  		})
   126  	}
   127  	m.mu.RUnlock()
   128  	return data
   129  }
   130  
   131  // MapStrAny returns a copy of the underlying data of the map as map[string]interface{}.
   132  func (m *ListMap) MapStrAny() map[string]interface{} {
   133  	m.mu.RLock()
   134  	var node *gListMapNode
   135  	var data map[string]interface{}
   136  	if m.list != nil {
   137  		data = make(map[string]interface{}, len(m.data))
   138  		m.list.IteratorAsc(func(e *glist.Element) bool {
   139  			node = e.Value.(*gListMapNode)
   140  			data[gconv.String(node.key)] = node.value
   141  			return true
   142  		})
   143  	}
   144  	m.mu.RUnlock()
   145  	return data
   146  }
   147  
   148  // FilterEmpty deletes all key-value pair of which the value is empty.
   149  func (m *ListMap) FilterEmpty() {
   150  	m.mu.Lock()
   151  	if m.list != nil {
   152  		keys := make([]interface{}, 0)
   153  		node := (*gListMapNode)(nil)
   154  		m.list.IteratorAsc(func(e *glist.Element) bool {
   155  			node = e.Value.(*gListMapNode)
   156  			if empty.IsEmpty(node.value) {
   157  				keys = append(keys, node.key)
   158  			}
   159  			return true
   160  		})
   161  		if len(keys) > 0 {
   162  			for _, key := range keys {
   163  				if e, ok := m.data[key]; ok {
   164  					delete(m.data, key)
   165  					m.list.Remove(e)
   166  				}
   167  			}
   168  		}
   169  	}
   170  	m.mu.Unlock()
   171  }
   172  
   173  // Set sets key-value to the map.
   174  func (m *ListMap) Set(key interface{}, value interface{}) {
   175  	m.mu.Lock()
   176  	if m.data == nil {
   177  		m.data = make(map[interface{}]*glist.Element)
   178  		m.list = glist.New()
   179  	}
   180  	if e, ok := m.data[key]; !ok {
   181  		m.data[key] = m.list.PushBack(&gListMapNode{key, value})
   182  	} else {
   183  		e.Value = &gListMapNode{key, value}
   184  	}
   185  	m.mu.Unlock()
   186  }
   187  
   188  // Sets batch sets key-values to the map.
   189  func (m *ListMap) Sets(data map[interface{}]interface{}) {
   190  	m.mu.Lock()
   191  	if m.data == nil {
   192  		m.data = make(map[interface{}]*glist.Element)
   193  		m.list = glist.New()
   194  	}
   195  	for key, value := range data {
   196  		if e, ok := m.data[key]; !ok {
   197  			m.data[key] = m.list.PushBack(&gListMapNode{key, value})
   198  		} else {
   199  			e.Value = &gListMapNode{key, value}
   200  		}
   201  	}
   202  	m.mu.Unlock()
   203  }
   204  
   205  // Search searches the map with given <key>.
   206  // Second return parameter <found> is true if key was found, otherwise false.
   207  func (m *ListMap) Search(key interface{}) (value interface{}, found bool) {
   208  	m.mu.RLock()
   209  	if m.data != nil {
   210  		if e, ok := m.data[key]; ok {
   211  			value = e.Value.(*gListMapNode).value
   212  			found = ok
   213  		}
   214  	}
   215  	m.mu.RUnlock()
   216  	return
   217  }
   218  
   219  // Get returns the value by given <key>.
   220  func (m *ListMap) Get(key interface{}) (value interface{}) {
   221  	m.mu.RLock()
   222  	if m.data != nil {
   223  		if e, ok := m.data[key]; ok {
   224  			value = e.Value.(*gListMapNode).value
   225  		}
   226  	}
   227  	m.mu.RUnlock()
   228  	return
   229  }
   230  
   231  // Pop retrieves and deletes an item from the map.
   232  func (m *ListMap) Pop() (key, value interface{}) {
   233  	m.mu.Lock()
   234  	defer m.mu.Unlock()
   235  	for k, e := range m.data {
   236  		value = e.Value.(*gListMapNode).value
   237  		delete(m.data, k)
   238  		m.list.Remove(e)
   239  		return k, value
   240  	}
   241  	return
   242  }
   243  
   244  // Pops retrieves and deletes <size> items from the map.
   245  // It returns all items if size == -1.
   246  func (m *ListMap) Pops(size int) map[interface{}]interface{} {
   247  	m.mu.Lock()
   248  	defer m.mu.Unlock()
   249  	if size > len(m.data) || size == -1 {
   250  		size = len(m.data)
   251  	}
   252  	if size == 0 {
   253  		return nil
   254  	}
   255  	index := 0
   256  	newMap := make(map[interface{}]interface{}, size)
   257  	for k, e := range m.data {
   258  		value := e.Value.(*gListMapNode).value
   259  		delete(m.data, k)
   260  		m.list.Remove(e)
   261  		newMap[k] = value
   262  		index++
   263  		if index == size {
   264  			break
   265  		}
   266  	}
   267  	return newMap
   268  }
   269  
   270  // doSetWithLockCheck checks whether value of the key exists with mutex.Lock,
   271  // if not exists, set value to the map with given <key>,
   272  // or else just return the existing value.
   273  //
   274  // When setting value, if <value> is type of <func() interface {}>,
   275  // it will be executed with mutex.Lock of the map,
   276  // and its return value will be set to the map with <key>.
   277  //
   278  // It returns value with given <key>.
   279  func (m *ListMap) doSetWithLockCheck(key interface{}, value interface{}) interface{} {
   280  	m.mu.Lock()
   281  	defer m.mu.Unlock()
   282  	if m.data == nil {
   283  		m.data = make(map[interface{}]*glist.Element)
   284  		m.list = glist.New()
   285  	}
   286  	if e, ok := m.data[key]; ok {
   287  		return e.Value.(*gListMapNode).value
   288  	}
   289  	if f, ok := value.(func() interface{}); ok {
   290  		value = f()
   291  	}
   292  	if value != nil {
   293  		m.data[key] = m.list.PushBack(&gListMapNode{key, value})
   294  	}
   295  	return value
   296  }
   297  
   298  // GetOrSet returns the value by key,
   299  // or sets value with given <value> if it does not exist and then returns this value.
   300  func (m *ListMap) GetOrSet(key interface{}, value interface{}) interface{} {
   301  	if v, ok := m.Search(key); !ok {
   302  		return m.doSetWithLockCheck(key, value)
   303  	} else {
   304  		return v
   305  	}
   306  }
   307  
   308  // GetOrSetFunc returns the value by key,
   309  // or sets value with returned value of callback function <f> if it does not exist
   310  // and then returns this value.
   311  func (m *ListMap) GetOrSetFunc(key interface{}, f func() interface{}) interface{} {
   312  	if v, ok := m.Search(key); !ok {
   313  		return m.doSetWithLockCheck(key, f())
   314  	} else {
   315  		return v
   316  	}
   317  }
   318  
   319  // GetOrSetFuncLock returns the value by key,
   320  // or sets value with returned value of callback function <f> if it does not exist
   321  // and then returns this value.
   322  //
   323  // GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function <f>
   324  // with mutex.Lock of the map.
   325  func (m *ListMap) GetOrSetFuncLock(key interface{}, f func() interface{}) interface{} {
   326  	if v, ok := m.Search(key); !ok {
   327  		return m.doSetWithLockCheck(key, f)
   328  	} else {
   329  		return v
   330  	}
   331  }
   332  
   333  // GetVar returns a Var with the value by given <key>.
   334  // The returned Var is un-concurrent safe.
   335  func (m *ListMap) GetVar(key interface{}) *gvar.Var {
   336  	return gvar.New(m.Get(key))
   337  }
   338  
   339  // GetVarOrSet returns a Var with result from GetVarOrSet.
   340  // The returned Var is un-concurrent safe.
   341  func (m *ListMap) GetVarOrSet(key interface{}, value interface{}) *gvar.Var {
   342  	return gvar.New(m.GetOrSet(key, value))
   343  }
   344  
   345  // GetVarOrSetFunc returns a Var with result from GetOrSetFunc.
   346  // The returned Var is un-concurrent safe.
   347  func (m *ListMap) GetVarOrSetFunc(key interface{}, f func() interface{}) *gvar.Var {
   348  	return gvar.New(m.GetOrSetFunc(key, f))
   349  }
   350  
   351  // GetVarOrSetFuncLock returns a Var with result from GetOrSetFuncLock.
   352  // The returned Var is un-concurrent safe.
   353  func (m *ListMap) GetVarOrSetFuncLock(key interface{}, f func() interface{}) *gvar.Var {
   354  	return gvar.New(m.GetOrSetFuncLock(key, f))
   355  }
   356  
   357  // SetIfNotExist sets <value> to the map if the <key> does not exist, and then returns true.
   358  // It returns false if <key> exists, and <value> would be ignored.
   359  func (m *ListMap) SetIfNotExist(key interface{}, value interface{}) bool {
   360  	if !m.Contains(key) {
   361  		m.doSetWithLockCheck(key, value)
   362  		return true
   363  	}
   364  	return false
   365  }
   366  
   367  // SetIfNotExistFunc sets value with return value of callback function <f>, and then returns true.
   368  // It returns false if <key> exists, and <value> would be ignored.
   369  func (m *ListMap) SetIfNotExistFunc(key interface{}, f func() interface{}) bool {
   370  	if !m.Contains(key) {
   371  		m.doSetWithLockCheck(key, f())
   372  		return true
   373  	}
   374  	return false
   375  }
   376  
   377  // SetIfNotExistFuncLock sets value with return value of callback function <f>, and then returns true.
   378  // It returns false if <key> exists, and <value> would be ignored.
   379  //
   380  // SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that
   381  // it executes function <f> with mutex.Lock of the map.
   382  func (m *ListMap) SetIfNotExistFuncLock(key interface{}, f func() interface{}) bool {
   383  	if !m.Contains(key) {
   384  		m.doSetWithLockCheck(key, f)
   385  		return true
   386  	}
   387  	return false
   388  }
   389  
   390  // Remove deletes value from map by given <key>, and return this deleted value.
   391  func (m *ListMap) Remove(key interface{}) (value interface{}) {
   392  	m.mu.Lock()
   393  	if m.data != nil {
   394  		if e, ok := m.data[key]; ok {
   395  			value = e.Value.(*gListMapNode).value
   396  			delete(m.data, key)
   397  			m.list.Remove(e)
   398  		}
   399  	}
   400  	m.mu.Unlock()
   401  	return
   402  }
   403  
   404  // Removes batch deletes values of the map by keys.
   405  func (m *ListMap) Removes(keys []interface{}) {
   406  	m.mu.Lock()
   407  	if m.data != nil {
   408  		for _, key := range keys {
   409  			if e, ok := m.data[key]; ok {
   410  				delete(m.data, key)
   411  				m.list.Remove(e)
   412  			}
   413  		}
   414  	}
   415  	m.mu.Unlock()
   416  }
   417  
   418  // Keys returns all keys of the map as a slice in ascending order.
   419  func (m *ListMap) Keys() []interface{} {
   420  	m.mu.RLock()
   421  	var (
   422  		keys  = make([]interface{}, m.list.Len())
   423  		index = 0
   424  	)
   425  	if m.list != nil {
   426  		m.list.IteratorAsc(func(e *glist.Element) bool {
   427  			keys[index] = e.Value.(*gListMapNode).key
   428  			index++
   429  			return true
   430  		})
   431  	}
   432  	m.mu.RUnlock()
   433  	return keys
   434  }
   435  
   436  // Values returns all values of the map as a slice.
   437  func (m *ListMap) Values() []interface{} {
   438  	m.mu.RLock()
   439  	var (
   440  		values = make([]interface{}, m.list.Len())
   441  		index  = 0
   442  	)
   443  	if m.list != nil {
   444  		m.list.IteratorAsc(func(e *glist.Element) bool {
   445  			values[index] = e.Value.(*gListMapNode).value
   446  			index++
   447  			return true
   448  		})
   449  	}
   450  	m.mu.RUnlock()
   451  	return values
   452  }
   453  
   454  // Contains checks whether a key exists.
   455  // It returns true if the <key> exists, or else false.
   456  func (m *ListMap) Contains(key interface{}) (ok bool) {
   457  	m.mu.RLock()
   458  	if m.data != nil {
   459  		_, ok = m.data[key]
   460  	}
   461  	m.mu.RUnlock()
   462  	return
   463  }
   464  
   465  // Size returns the size of the map.
   466  func (m *ListMap) Size() (size int) {
   467  	m.mu.RLock()
   468  	size = len(m.data)
   469  	m.mu.RUnlock()
   470  	return
   471  }
   472  
   473  // IsEmpty checks whether the map is empty.
   474  // It returns true if map is empty, or else false.
   475  func (m *ListMap) IsEmpty() bool {
   476  	return m.Size() == 0
   477  }
   478  
   479  // Flip exchanges key-value of the map to value-key.
   480  func (m *ListMap) Flip() {
   481  	data := m.Map()
   482  	m.Clear()
   483  	for key, value := range data {
   484  		m.Set(value, key)
   485  	}
   486  }
   487  
   488  // Merge merges two link maps.
   489  // The <other> map will be merged into the map <m>.
   490  func (m *ListMap) Merge(other *ListMap) {
   491  	m.mu.Lock()
   492  	defer m.mu.Unlock()
   493  	if m.data == nil {
   494  		m.data = make(map[interface{}]*glist.Element)
   495  		m.list = glist.New()
   496  	}
   497  	if other != m {
   498  		other.mu.RLock()
   499  		defer other.mu.RUnlock()
   500  	}
   501  	node := (*gListMapNode)(nil)
   502  	other.list.IteratorAsc(func(e *glist.Element) bool {
   503  		node = e.Value.(*gListMapNode)
   504  		if e, ok := m.data[node.key]; !ok {
   505  			m.data[node.key] = m.list.PushBack(&gListMapNode{node.key, node.value})
   506  		} else {
   507  			e.Value = &gListMapNode{node.key, node.value}
   508  		}
   509  		return true
   510  	})
   511  }
   512  
   513  // String returns the map as a string.
   514  func (m *ListMap) String() string {
   515  	b, _ := m.MarshalJSON()
   516  	return string(b)
   517  }
   518  
   519  // MarshalJSON implements the interface MarshalJSON for json.Marshal.
   520  func (m *ListMap) MarshalJSON() ([]byte, error) {
   521  	return json.Marshal(gconv.Map(m.Map()))
   522  }
   523  
   524  // UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal.
   525  func (m *ListMap) UnmarshalJSON(b []byte) error {
   526  	m.mu.Lock()
   527  	defer m.mu.Unlock()
   528  	if m.data == nil {
   529  		m.data = make(map[interface{}]*glist.Element)
   530  		m.list = glist.New()
   531  	}
   532  	var data map[string]interface{}
   533  	if err := json.UnmarshalUseNumber(b, &data); err != nil {
   534  		return err
   535  	}
   536  	for key, value := range data {
   537  		if e, ok := m.data[key]; !ok {
   538  			m.data[key] = m.list.PushBack(&gListMapNode{key, value})
   539  		} else {
   540  			e.Value = &gListMapNode{key, value}
   541  		}
   542  	}
   543  	return nil
   544  }
   545  
   546  // UnmarshalValue is an interface implement which sets any type of value for map.
   547  func (m *ListMap) UnmarshalValue(value interface{}) (err error) {
   548  	m.mu.Lock()
   549  	defer m.mu.Unlock()
   550  	if m.data == nil {
   551  		m.data = make(map[interface{}]*glist.Element)
   552  		m.list = glist.New()
   553  	}
   554  	for k, v := range gconv.Map(value) {
   555  		if e, ok := m.data[k]; !ok {
   556  			m.data[k] = m.list.PushBack(&gListMapNode{k, v})
   557  		} else {
   558  			e.Value = &gListMapNode{k, v}
   559  		}
   560  	}
   561  	return
   562  }