github.com/whatap/golib@v0.0.22/util/hmap/LinkedMap.go (about)

     1  package hmap
     2  
     3  import (
     4  	"bytes"
     5  	"sort"
     6  	"sync"
     7  )
     8  
     9  type LinkedMap struct {
    10  	table      []*LinkedEntry
    11  	header     *LinkedEntry
    12  	count      int
    13  	threshold  int
    14  	loadFactor float32
    15  	lock       sync.Mutex
    16  	max        int
    17  }
    18  
    19  func NewLinkedMapDefault() *LinkedMap {
    20  	return NewLinkedMap(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR)
    21  }
    22  
    23  func NewLinkedMap(initCapacity int, loadFactor float32) *LinkedMap {
    24  
    25  	this := new(LinkedMap)
    26  	this.loadFactor = float32(loadFactor)
    27  	this.table = make([]*LinkedEntry, initCapacity)
    28  	this.header = &LinkedEntry{}
    29  	this.header.link_next = this.header
    30  	this.header.link_prev = this.header
    31  	this.threshold = int(float32(initCapacity) * loadFactor)
    32  	return this
    33  }
    34  
    35  func (this *LinkedMap) Size() int {
    36  	return this.count
    37  }
    38  
    39  func (this *LinkedMap) KeyArray() []LinkedKey {
    40  	this.lock.Lock()
    41  	defer this.lock.Unlock()
    42  
    43  	_keys := make([]LinkedKey, this.Size())
    44  	en := this.Keys()
    45  	for i := 0; i < len(_keys); i++ {
    46  		_keys[i] = en.NextElement().(LinkedKey)
    47  	}
    48  	return _keys
    49  }
    50  
    51  type EnumerImpl struct {
    52  	parent *LinkedMap
    53  	entry  *LinkedEntry
    54  	rtype  int
    55  }
    56  
    57  func (this *EnumerImpl) HasMoreElements() bool {
    58  	return this.entry != nil && this.parent.header != this.entry
    59  }
    60  
    61  func (this *EnumerImpl) NextElement() interface{} {
    62  	if this.HasMoreElements() {
    63  		e := this.entry
    64  		this.entry = e.link_next
    65  		switch this.rtype {
    66  		case 1:
    67  			return e.GetKey()
    68  		case 2:
    69  			return e.GetValue()
    70  		case 3:
    71  			return e
    72  		}
    73  	}
    74  	return ""
    75  }
    76  func (this *LinkedMap) Keys() Enumeration {
    77  	return &EnumerImpl{parent: this, entry: this.header.link_next, rtype: 1}
    78  }
    79  func (this *LinkedMap) Values() Enumeration {
    80  	return &EnumerImpl{parent: this, entry: this.header.link_next, rtype: 2}
    81  }
    82  func (this *LinkedMap) Entries() Enumeration {
    83  	return &EnumerImpl{parent: this, entry: this.header.link_next, rtype: 3}
    84  }
    85  
    86  func (this *LinkedMap) ContainsKey(key LinkedKey) bool {
    87  	this.lock.Lock()
    88  	defer this.lock.Unlock()
    89  
    90  	tab := this.table
    91  	index := this.hash(key) % uint(len(tab))
    92  	for e := tab[index]; e != nil; e = e.hash_next {
    93  		if e.key.Equals(key) {
    94  			return true
    95  		}
    96  	}
    97  	return false
    98  
    99  }
   100  func (this *LinkedMap) Get(key LinkedKey) interface{} {
   101  	this.lock.Lock()
   102  	defer this.lock.Unlock()
   103  
   104  	tab := this.table
   105  	index := this.hash(key) % uint(len(tab))
   106  	for e := tab[index]; e != nil; e = e.hash_next {
   107  		if e.key.Equals(key) {
   108  			return e.value
   109  		}
   110  	}
   111  	return nil
   112  }
   113  func (this *LinkedMap) GetFirstKey() LinkedKey {
   114  	this.lock.Lock()
   115  	defer this.lock.Unlock()
   116  
   117  	return this.header.link_next.key
   118  }
   119  
   120  func (this *LinkedMap) GetLastKey() LinkedKey {
   121  	this.lock.Lock()
   122  	defer this.lock.Unlock()
   123  	return this.header.link_prev.key
   124  }
   125  
   126  func (this *LinkedMap) GetFirstValue() interface{} {
   127  	this.lock.Lock()
   128  	defer this.lock.Unlock()
   129  
   130  	return this.header.link_next.value
   131  }
   132  
   133  func (this *LinkedMap) GetLastValue() interface{} {
   134  	this.lock.Lock()
   135  	defer this.lock.Unlock()
   136  
   137  	return this.header.link_prev.value
   138  }
   139  func (this *LinkedMap) hash(key LinkedKey) uint {
   140  	return key.Hash()
   141  }
   142  
   143  func (this *LinkedMap) rehash() {
   144  	oldCapacity := len(this.table)
   145  	oldMap := this.table
   146  	newCapacity := oldCapacity*2 + 1
   147  	newMap := make([]*LinkedEntry, newCapacity)
   148  	this.threshold = int(float32(newCapacity) * this.loadFactor)
   149  	this.table = newMap
   150  	for i := oldCapacity; i > 0; i-- {
   151  		for old := oldMap[i-1]; old != nil; {
   152  			e := old
   153  			old = old.hash_next
   154  			index := uint(e.keyHash % uint(newCapacity))
   155  			e.hash_next = newMap[index]
   156  			newMap[index] = e
   157  		}
   158  	}
   159  }
   160  
   161  func (this *LinkedMap) SetMax(max int) *LinkedMap {
   162  	this.max = max
   163  	return this
   164  }
   165  func (this *LinkedMap) Put(key LinkedKey, value interface{}) interface{} {
   166  	this.lock.Lock()
   167  	defer this.lock.Unlock()
   168  	return this.put(key, value, PUT_LAST)
   169  }
   170  func (this *LinkedMap) PutLast(key LinkedKey, value interface{}) interface{} {
   171  	this.lock.Lock()
   172  	defer this.lock.Unlock()
   173  	return this.put(key, value, PUT_FORCE_LAST)
   174  }
   175  func (this *LinkedMap) PutFirst(key LinkedKey, value interface{}) interface{} {
   176  	this.lock.Lock()
   177  	defer this.lock.Unlock()
   178  	return this.put(key, value, PUT_FORCE_FIRST)
   179  }
   180  func (this *LinkedMap) put(key LinkedKey, value interface{}, m PUT_MODE) interface{} {
   181  
   182  	tab := this.table
   183  	keyHash := this.hash(key)
   184  	index := keyHash % uint(len(tab))
   185  	for e := tab[index]; e != nil; e = e.hash_next {
   186  		if e.key.Equals(key) {
   187  			old := e.value
   188  			e.value = value
   189  			switch m {
   190  			case PUT_FORCE_FIRST:
   191  				if this.header.link_next != e {
   192  					this.unchain(e)
   193  					this.chain(this.header, this.header.link_next, e)
   194  				}
   195  			case PUT_FORCE_LAST:
   196  				if this.header.link_prev != e {
   197  					this.unchain(e)
   198  					this.chain(this.header.link_prev, this.header, e)
   199  				}
   200  			}
   201  			return old
   202  		}
   203  	}
   204  	if this.max > 0 {
   205  		switch m {
   206  		case PUT_FORCE_FIRST, PUT_FIRST:
   207  			for this.count >= this.max {
   208  				k := this.header.link_prev.key
   209  				this.remove(k)
   210  			}
   211  		case PUT_FORCE_LAST, PUT_LAST:
   212  			for this.count >= this.max {
   213  				// removeFirst();
   214  				k := this.header.link_next.key
   215  				this.remove(k)
   216  			}
   217  			break
   218  		}
   219  	}
   220  	if this.count >= this.threshold {
   221  		this.rehash()
   222  		tab = this.table
   223  		index = keyHash % uint(len(tab))
   224  	}
   225  	e := &LinkedEntry{key: key, keyHash: keyHash, value: value, hash_next: tab[index]}
   226  	tab[index] = e
   227  	switch m {
   228  	case PUT_FORCE_FIRST, PUT_FIRST:
   229  		this.chain(this.header, this.header.link_next, e)
   230  	case PUT_FORCE_LAST, PUT_LAST:
   231  		this.chain(this.header.link_prev, this.header, e)
   232  	}
   233  	this.count++
   234  	return ""
   235  }
   236  
   237  func (this *LinkedMap) Remove(key LinkedKey) interface{} {
   238  	this.lock.Lock()
   239  	defer this.lock.Unlock()
   240  
   241  	return this.remove(key)
   242  }
   243  func (this *LinkedMap) RemoveFirst() interface{} {
   244  	if this.IsEmpty() {
   245  		return 0
   246  	}
   247  	this.lock.Lock()
   248  	defer this.lock.Unlock()
   249  	return this.remove(this.header.link_next.key)
   250  }
   251  
   252  func (this *LinkedMap) RemoveLast() interface{} {
   253  	if this.IsEmpty() {
   254  		return 0
   255  	}
   256  	this.lock.Lock()
   257  	defer this.lock.Unlock()
   258  	return this.remove(this.header.link_prev.key)
   259  }
   260  
   261  func (this *LinkedMap) remove(key LinkedKey) interface{} {
   262  
   263  	tab := this.table
   264  	index := this.hash(key) % uint(len(tab))
   265  	e := tab[index]
   266  	var prev *LinkedEntry = nil
   267  	for e != nil {
   268  		if e.key.Equals(key) {
   269  			if prev != nil {
   270  				prev.hash_next = e.hash_next
   271  			} else {
   272  				tab[index] = e.hash_next
   273  			}
   274  			this.count--
   275  			oldValue := e.value
   276  			e.value = nil
   277  			//
   278  			this.unchain(e)
   279  			return oldValue
   280  		}
   281  		prev = e
   282  		e = e.hash_next
   283  	}
   284  	return nil
   285  }
   286  
   287  func (this *LinkedMap) IsEmpty() bool {
   288  	return this.count == 0
   289  }
   290  func (this *LinkedMap) IsFull() bool {
   291  	return this.max > 0 && this.max <= this.count
   292  }
   293  
   294  func (this *LinkedMap) Clear() {
   295  	this.lock.Lock()
   296  	defer this.lock.Unlock()
   297  	this.clear()
   298  }
   299  func (this *LinkedMap) clear() {
   300  	tab := this.table
   301  	for index := len(tab) - 1; index >= 0; index-- {
   302  		tab[index] = nil
   303  	}
   304  	this.header.link_next = this.header
   305  	this.header.link_prev = this.header
   306  	this.count = 0
   307  }
   308  
   309  func (this *LinkedMap) chain(link_prev *LinkedEntry, link_next *LinkedEntry, e *LinkedEntry) {
   310  	e.link_prev = link_prev
   311  	e.link_next = link_next
   312  	link_prev.link_next = e
   313  	link_next.link_prev = e
   314  }
   315  
   316  func (this *LinkedMap) unchain(e *LinkedEntry) {
   317  	e.link_prev.link_next = e.link_next
   318  	e.link_next.link_prev = e.link_prev
   319  	e.link_prev = nil
   320  	e.link_next = nil
   321  }
   322  
   323  type mapSortable struct {
   324  	compare func(a, b LinkedKey) bool
   325  	data    []*LinkedEntry
   326  }
   327  
   328  func (this mapSortable) Len() int {
   329  	return len(this.data)
   330  }
   331  func (this mapSortable) Less(i, j int) bool {
   332  	return this.compare(this.data[i].GetKey(), this.data[j].GetKey())
   333  }
   334  
   335  func (this mapSortable) Swap(i, j int) {
   336  	this.data[i], this.data[j] = this.data[j], this.data[i]
   337  }
   338  
   339  func (this *LinkedMap) Sort(c func(k1, k2 LinkedKey) bool) {
   340  	this.lock.Lock()
   341  	defer this.lock.Unlock()
   342  
   343  	sz := this.Size()
   344  	list := make([]*LinkedEntry, sz)
   345  	en := this.Entries()
   346  	for i := 0; i < sz; i++ {
   347  		list[i] = en.NextElement().(*LinkedEntry)
   348  	}
   349  	sort.Sort(mapSortable{compare: c, data: list})
   350  
   351  	this.clear()
   352  	for i := 0; i < sz; i++ {
   353  		this.put(list[i].GetKey(), list[i].GetValue(), PUT_LAST)
   354  	}
   355  }
   356  
   357  func (this *LinkedMap) ToString() string {
   358  	this.lock.Lock()
   359  	defer this.lock.Unlock()
   360  
   361  	var buffer bytes.Buffer
   362  	x := this.Entries()
   363  	buffer.WriteString("{")
   364  	for i := 0; x.HasMoreElements(); i++ {
   365  		if i > 0 {
   366  			buffer.WriteString(", ")
   367  		}
   368  		e := x.NextElement().(*LinkedEntry)
   369  		buffer.WriteString(e.ToString())
   370  	}
   371  	buffer.WriteString("}")
   372  	return buffer.String()
   373  }