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

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