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

     1  package hmap
     2  
     3  import (
     4  	"bytes"
     5  	"sort"
     6  	"sync"
     7  
     8  	"github.com/whatap/golib/io"
     9  )
    10  
    11  type LongFloatLinkedMap struct {
    12  	table      []*LongFloatLinkedEntry
    13  	header     *LongFloatLinkedEntry
    14  	count      int
    15  	threshold  int
    16  	loadFactor float32
    17  	NONE       float32
    18  	lock       sync.Mutex
    19  	max        int
    20  }
    21  
    22  func NewLongFloatLinkedMap() *LongFloatLinkedMap {
    23  
    24  	initCapacity := DEFAULT_CAPACITY
    25  	loadFactor := DEFAULT_LOAD_FACTOR
    26  
    27  	this := new(LongFloatLinkedMap)
    28  	this.loadFactor = float32(loadFactor)
    29  	this.table = make([]*LongFloatLinkedEntry, initCapacity)
    30  	this.header = &LongFloatLinkedEntry{}
    31  	this.header.link_next = this.header
    32  	this.header.link_prev = this.header
    33  	this.threshold = int(float64(initCapacity) * loadFactor)
    34  	return this
    35  }
    36  
    37  func (this *LongFloatLinkedMap) Size() int {
    38  	return this.count
    39  }
    40  
    41  func (this *LongFloatLinkedMap) KeyArray() []int64 {
    42  	this.lock.Lock()
    43  	defer this.lock.Unlock()
    44  
    45  	_keys := make([]int64, this.Size())
    46  	en := this.Keys()
    47  	for i := 0; i < len(_keys); i++ {
    48  		_keys[i] = en.NextLong()
    49  	}
    50  	return _keys
    51  }
    52  
    53  type LongFloatEnumerImpl struct {
    54  	parent *LongFloatLinkedMap
    55  	entry  *LongFloatLinkedEntry
    56  }
    57  
    58  func (this *LongFloatEnumerImpl) HasMoreElements() bool {
    59  	return this.entry != nil && this.parent.header != this.entry
    60  }
    61  func (this *LongFloatEnumerImpl) NextLong() int64 {
    62  	if this.HasMoreElements() {
    63  		e := this.entry
    64  		this.entry = e.link_next
    65  		return e.key
    66  	}
    67  	return 0
    68  }
    69  func (this *LongFloatEnumerImpl) NextFloat() float32 {
    70  	if this.HasMoreElements() {
    71  		e := this.entry
    72  		this.entry = e.link_next
    73  		return e.value
    74  	}
    75  	return this.parent.NONE
    76  }
    77  func (this *LongFloatEnumerImpl) NextElement() interface{} {
    78  	if this.HasMoreElements() {
    79  		e := this.entry
    80  		this.entry = e.link_next
    81  		return e
    82  	}
    83  	return nil
    84  }
    85  func (this *LongFloatLinkedMap) Keys() LongEnumer {
    86  	return &LongFloatEnumerImpl{parent: this, entry: this.header.link_next}
    87  }
    88  func (this *LongFloatLinkedMap) Values() FloatEnumer {
    89  	return &LongFloatEnumerImpl{parent: this, entry: this.header.link_next}
    90  }
    91  func (this *LongFloatLinkedMap) Entries() Enumeration {
    92  	return &LongFloatEnumerImpl{parent: this, entry: this.header.link_next}
    93  }
    94  
    95  func (this *LongFloatLinkedMap) ContainsValue(value float32) bool {
    96  	this.lock.Lock()
    97  	defer this.lock.Unlock()
    98  
    99  	tab := this.table
   100  	for i := len(tab); i > 0; i-- {
   101  		for e := tab[i]; e != nil; e = e.hash_next {
   102  			if e.value == value {
   103  				return true
   104  			}
   105  		}
   106  	}
   107  	return false
   108  }
   109  func (this *LongFloatLinkedMap) ContainsKey(key int64) bool {
   110  	this.lock.Lock()
   111  	defer this.lock.Unlock()
   112  
   113  	tab := this.table
   114  	index := this.hash(key) % uint(len(tab))
   115  	for e := tab[index]; e != nil; e = e.hash_next {
   116  		if e.key == key {
   117  			return true
   118  		}
   119  	}
   120  	return false
   121  
   122  }
   123  func (this *LongFloatLinkedMap) Get(key int64) float32 {
   124  	this.lock.Lock()
   125  	defer this.lock.Unlock()
   126  
   127  	tab := this.table
   128  	index := this.hash(key) % uint(len(tab))
   129  	for e := tab[index]; e != nil; e = e.hash_next {
   130  		if e.key == key {
   131  			return e.value
   132  		}
   133  	}
   134  	return this.NONE
   135  }
   136  func (this *LongFloatLinkedMap) GetFirstKey() int64 {
   137  	this.lock.Lock()
   138  	defer this.lock.Unlock()
   139  
   140  	return this.header.link_next.key
   141  }
   142  
   143  func (this *LongFloatLinkedMap) GetLastKey() int64 {
   144  	this.lock.Lock()
   145  	defer this.lock.Unlock()
   146  	return this.header.link_prev.key
   147  }
   148  
   149  func (this *LongFloatLinkedMap) GetFirstValue() float32 {
   150  	this.lock.Lock()
   151  	defer this.lock.Unlock()
   152  
   153  	return this.header.link_next.value
   154  }
   155  
   156  func (this *LongFloatLinkedMap) GetLastValue() float32 {
   157  	this.lock.Lock()
   158  	defer this.lock.Unlock()
   159  
   160  	return this.header.link_prev.value
   161  }
   162  func (this *LongFloatLinkedMap) hash(key int64) uint {
   163  	return uint(key)
   164  }
   165  
   166  func (this *LongFloatLinkedMap) rehash() {
   167  	oldCapacity := len(this.table)
   168  	oldMap := this.table
   169  	newCapacity := oldCapacity*2 + 1
   170  	newMap := make([]*LongFloatLinkedEntry, newCapacity)
   171  	this.threshold = int(float32(newCapacity) * this.loadFactor)
   172  	this.table = newMap
   173  	for i := oldCapacity; i > 0; i-- {
   174  		for old := oldMap[i-1]; old != nil; {
   175  			e := old
   176  			old = old.hash_next
   177  			key := e.key
   178  			index := int(this.hash(key) % uint(newCapacity))
   179  			e.hash_next = newMap[index]
   180  			newMap[index] = e
   181  		}
   182  	}
   183  }
   184  
   185  func (this *LongFloatLinkedMap) SetMax(max int) *LongFloatLinkedMap {
   186  	this.max = max
   187  	return this
   188  }
   189  func (this *LongFloatLinkedMap) Put(key int64, value float32) float32 {
   190  	this.lock.Lock()
   191  	defer this.lock.Unlock()
   192  	return this.put(key, value, PUT_LAST)
   193  }
   194  func (this *LongFloatLinkedMap) PutLast(key int64, value float32) float32 {
   195  	this.lock.Lock()
   196  	defer this.lock.Unlock()
   197  	return this.put(key, value, PUT_FORCE_LAST)
   198  }
   199  func (this *LongFloatLinkedMap) PutFirst(key int64, value float32) float32 {
   200  	this.lock.Lock()
   201  	defer this.lock.Unlock()
   202  	return this.put(key, value, PUT_FORCE_FIRST)
   203  }
   204  func (this *LongFloatLinkedMap) put(key int64, value float32, m PUT_MODE) float32 {
   205  
   206  	tab := this.table
   207  	index := this.hash(key) % uint(len(tab))
   208  	for e := tab[index]; e != nil; e = e.hash_next {
   209  		if e.key == key {
   210  			old := e.value
   211  			e.value = value
   212  			switch m {
   213  			case PUT_FORCE_FIRST:
   214  				if this.header.link_next != e {
   215  					this.unchain(e)
   216  					this.chain(this.header, this.header.link_next, e)
   217  				}
   218  			case PUT_FORCE_LAST:
   219  				if this.header.link_prev != e {
   220  					this.unchain(e)
   221  					this.chain(this.header.link_prev, this.header, e)
   222  				}
   223  			}
   224  			return old
   225  		}
   226  	}
   227  	if this.max > 0 {
   228  		switch m {
   229  		case PUT_FORCE_FIRST, PUT_FIRST:
   230  			for this.count >= this.max {
   231  				k := this.header.link_prev.key
   232  				this.remove(k)
   233  			}
   234  		case PUT_FORCE_LAST, PUT_LAST:
   235  			for this.count >= this.max {
   236  				// removeFirst();
   237  				k := this.header.link_next.key
   238  				this.remove(k)
   239  			}
   240  			break
   241  		}
   242  	}
   243  	if this.count >= this.threshold {
   244  		this.rehash()
   245  		tab = this.table
   246  		index = this.hash(key) % uint(len(tab))
   247  	}
   248  	e := &LongFloatLinkedEntry{key: key, value: value, hash_next: tab[index]}
   249  	tab[index] = e
   250  	switch m {
   251  	case PUT_FORCE_FIRST, PUT_FIRST:
   252  		this.chain(this.header, this.header.link_next, e)
   253  	case PUT_FORCE_LAST, PUT_LAST:
   254  		this.chain(this.header.link_prev, this.header, e)
   255  	}
   256  	this.count++
   257  	return this.NONE
   258  }
   259  
   260  func (this *LongFloatLinkedMap) Add(key int64, value float32) float32 {
   261  	this.lock.Lock()
   262  	defer this.lock.Unlock()
   263  
   264  	return this.add(key, value, PUT_LAST)
   265  }
   266  func (this *LongFloatLinkedMap) AddLast(key int64, value float32) float32 {
   267  	this.lock.Lock()
   268  	defer this.lock.Unlock()
   269  
   270  	return this.add(key, value, PUT_FORCE_LAST)
   271  }
   272  func (this *LongFloatLinkedMap) AddFirst(key int64, value float32) float32 {
   273  	this.lock.Lock()
   274  	defer this.lock.Unlock()
   275  
   276  	return this.add(key, value, PUT_FORCE_FIRST)
   277  }
   278  
   279  func (this *LongFloatLinkedMap) add(key int64, value float32, m PUT_MODE) float32 {
   280  	tab := this.table
   281  	index := this.hash(key) % uint(len(tab))
   282  	for e := tab[index]; e != nil; e = e.hash_next {
   283  		if e.key == key {
   284  			old := e.value
   285  			e.value += value
   286  			switch m {
   287  			case PUT_FORCE_FIRST:
   288  				if this.header.link_next != e {
   289  					this.unchain(e)
   290  					this.chain(this.header, this.header.link_next, e)
   291  				}
   292  			case PUT_FORCE_LAST:
   293  				if this.header.link_prev != e {
   294  					this.unchain(e)
   295  					this.chain(this.header.link_prev, this.header, e)
   296  				}
   297  			}
   298  			return old
   299  		}
   300  	}
   301  	if this.max > 0 {
   302  		switch m {
   303  		case PUT_FORCE_FIRST, PUT_FIRST:
   304  			for this.count >= this.max {
   305  				k := this.header.link_prev.key
   306  				this.remove(k)
   307  			}
   308  		case PUT_FORCE_LAST, PUT_LAST:
   309  			for this.count >= this.max {
   310  				k := this.header.link_next.key
   311  				this.remove(k)
   312  			}
   313  			break
   314  		}
   315  	}
   316  	if this.count >= this.threshold {
   317  		this.rehash()
   318  		tab = this.table
   319  		index = this.hash(key) % uint(len(tab))
   320  	}
   321  	e := &LongFloatLinkedEntry{key: key, value: value, hash_next: tab[index]}
   322  	tab[index] = e
   323  	switch m {
   324  	case PUT_FORCE_FIRST, PUT_FIRST:
   325  		this.chain(this.header, this.header.link_next, e)
   326  	case PUT_FORCE_LAST, PUT_LAST:
   327  		this.chain(this.header.link_prev, this.header, e)
   328  	}
   329  	this.count++
   330  	return this.NONE
   331  }
   332  func (this *LongFloatLinkedMap) Remove(key int64) float32 {
   333  	this.lock.Lock()
   334  	defer this.lock.Unlock()
   335  
   336  	return this.remove(key)
   337  }
   338  func (this *LongFloatLinkedMap) RemoveFirst() float32 {
   339  	if this.IsEmpty() {
   340  		return 0
   341  	}
   342  	this.lock.Lock()
   343  	defer this.lock.Unlock()
   344  	return this.remove(this.header.link_next.key)
   345  }
   346  
   347  func (this *LongFloatLinkedMap) RemoveLast() float32 {
   348  	if this.IsEmpty() {
   349  		return 0
   350  	}
   351  	this.lock.Lock()
   352  	defer this.lock.Unlock()
   353  	return this.remove(this.header.link_prev.key)
   354  }
   355  
   356  func (this *LongFloatLinkedMap) remove(key int64) float32 {
   357  
   358  	tab := this.table
   359  	index := this.hash(key) % uint(len(tab))
   360  	e := tab[index]
   361  	var prev *LongFloatLinkedEntry = nil
   362  	for e != nil {
   363  		if e.key == key {
   364  			if prev != nil {
   365  				prev.hash_next = e.hash_next
   366  			} else {
   367  				tab[index] = e.hash_next
   368  			}
   369  			this.count--
   370  			oldValue := e.value
   371  			e.value = this.NONE
   372  			//
   373  			this.unchain(e)
   374  			return oldValue
   375  		}
   376  		prev = e
   377  		e = e.hash_next
   378  	}
   379  	return this.NONE
   380  }
   381  
   382  func (this *LongFloatLinkedMap) IsEmpty() bool {
   383  	return this.count == 0
   384  }
   385  func (this *LongFloatLinkedMap) IsFull() bool {
   386  	return this.max > 0 && this.max <= this.count
   387  }
   388  
   389  func (this *LongFloatLinkedMap) Clear() {
   390  	this.lock.Lock()
   391  	defer this.lock.Unlock()
   392  	this.clear()
   393  }
   394  func (this *LongFloatLinkedMap) clear() {
   395  	tab := this.table
   396  	for index := len(tab) - 1; index >= 0; index-- {
   397  		tab[index] = nil
   398  	}
   399  	this.header.link_next = this.header
   400  	this.header.link_prev = this.header
   401  	this.count = 0
   402  }
   403  
   404  func (this *LongFloatLinkedMap) chain(link_prev *LongFloatLinkedEntry, link_next *LongFloatLinkedEntry, e *LongFloatLinkedEntry) {
   405  	e.link_prev = link_prev
   406  	e.link_next = link_next
   407  	link_prev.link_next = e
   408  	link_next.link_prev = e
   409  }
   410  
   411  func (this *LongFloatLinkedMap) unchain(e *LongFloatLinkedEntry) {
   412  	e.link_prev.link_next = e.link_next
   413  	e.link_next.link_prev = e.link_prev
   414  	e.link_prev = nil
   415  	e.link_next = nil
   416  }
   417  
   418  type longFloatSortable struct {
   419  	compare func(a, b int64) bool
   420  	data    []*LongFloatLinkedEntry
   421  }
   422  
   423  func (this longFloatSortable) Len() int {
   424  	return len(this.data)
   425  }
   426  func (this longFloatSortable) Less(i, j int) bool {
   427  	return this.compare(this.data[i].GetKey(), this.data[j].GetKey())
   428  }
   429  
   430  func (this longFloatSortable) Swap(i, j int) {
   431  	this.data[i], this.data[j] = this.data[j], this.data[i]
   432  }
   433  
   434  func (this *LongFloatLinkedMap) Sort(c func(k1, k2 int64) bool) {
   435  	this.lock.Lock()
   436  	defer this.lock.Unlock()
   437  
   438  	sz := this.Size()
   439  	list := make([]*LongFloatLinkedEntry, sz)
   440  	en := this.Entries()
   441  	for i := 0; i < sz; i++ {
   442  		list[i] = en.NextElement().(*LongFloatLinkedEntry)
   443  	}
   444  	sort.Sort(longFloatSortable{compare: c, data: list})
   445  
   446  	this.clear()
   447  	for i := 0; i < sz; i++ {
   448  		this.put(list[i].GetKey(), list[i].GetValue(), PUT_LAST)
   449  	}
   450  }
   451  
   452  func (this *LongFloatLinkedMap) ToBytes(dout *io.DataOutputX) {
   453  	dout.WriteDecimal(int64(this.Size()))
   454  	en := this.Entries()
   455  	for en.HasMoreElements() {
   456  		e := en.NextElement().(LongFloatLinkedEntry)
   457  		dout.WriteDecimal(int64(e.GetKey()))
   458  		dout.WriteFloat(e.GetValue())
   459  	}
   460  }
   461  
   462  func (this *LongFloatLinkedMap) ToObject(din *io.DataInputX) *LongFloatLinkedMap {
   463  	cnt := int(din.ReadDecimal())
   464  	for i := 0; i < cnt; i++ {
   465  		key := int64(din.ReadDecimal())
   466  		value := din.ReadFloat()
   467  		this.Put(key, value)
   468  	}
   469  	return this
   470  }
   471  func (this *LongFloatLinkedMap) ToString() string {
   472  	this.lock.Lock()
   473  	defer this.lock.Unlock()
   474  
   475  	var buffer bytes.Buffer
   476  	x := this.Entries()
   477  	buffer.WriteString("{")
   478  	for i := 0; x.HasMoreElements(); i++ {
   479  		if i > 0 {
   480  			buffer.WriteString(", ")
   481  		}
   482  		e := x.NextElement().(*LongFloatLinkedEntry)
   483  		buffer.WriteString(e.ToString())
   484  	}
   485  	buffer.WriteString("}")
   486  	return buffer.String()
   487  }