github.com/whatap/golib@v0.0.22/util/hmap/IntIntLinkedMap.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 IntIntLinkedMap struct {
    12  	table      []*IntIntLinkedEntry
    13  	header     *IntIntLinkedEntry
    14  	count      int
    15  	threshold  int
    16  	loadFactor float32
    17  	NONE       int32
    18  	lock       sync.Mutex
    19  	max        int
    20  }
    21  
    22  func NewIntIntLinkedMap() *IntIntLinkedMap {
    23  
    24  	initCapacity := DEFAULT_CAPACITY
    25  	loadFactor := DEFAULT_LOAD_FACTOR
    26  
    27  	this := new(IntIntLinkedMap)
    28  	this.loadFactor = float32(loadFactor)
    29  	this.table = make([]*IntIntLinkedEntry, initCapacity)
    30  	this.header = &IntIntLinkedEntry{}
    31  	this.header.link_next = this.header
    32  	this.header.link_prev = this.header
    33  	this.threshold = int(float64(initCapacity) * loadFactor)
    34  
    35  	//fmt.Printf("this=%p, threshold=%d \r\n", this, this.threshold)
    36  
    37  	return this
    38  }
    39  
    40  func (this *IntIntLinkedMap) Size() int {
    41  	return this.count
    42  }
    43  
    44  func (this *IntIntLinkedMap) KeyArray() []int32 {
    45  	this.lock.Lock()
    46  	defer this.lock.Unlock()
    47  
    48  	_keys := make([]int32, this.Size())
    49  	en := this.Keys()
    50  	for i := 0; i < len(_keys); i++ {
    51  		_keys[i] = en.NextInt()
    52  	}
    53  	return _keys
    54  }
    55  
    56  type IntIntEnumer struct {
    57  	isKey  bool
    58  	parent *IntIntLinkedMap
    59  	entry  *IntIntLinkedEntry
    60  }
    61  
    62  func (this *IntIntEnumer) HasMoreElements() bool {
    63  	return this.entry != nil && this.parent.header != this.entry
    64  }
    65  func (this *IntIntEnumer) NextInt() int32 {
    66  	if this.HasMoreElements() {
    67  		e := this.entry
    68  		this.entry = e.link_next
    69  		if this.isKey {
    70  			return e.key
    71  		} else {
    72  			return e.value
    73  		}
    74  	}
    75  	return 0
    76  }
    77  func (this *IntIntEnumer) 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 *IntIntLinkedMap) Keys() IntEnumer {
    86  	return &IntIntEnumer{isKey: true, parent: this, entry: this.header.link_next}
    87  }
    88  func (this *IntIntLinkedMap) Values() IntEnumer {
    89  	return &IntIntEnumer{isKey: false, parent: this, entry: this.header.link_next}
    90  }
    91  func (this *IntIntLinkedMap) Entries() Enumeration {
    92  	return &IntIntEnumer{parent: this, entry: this.header.link_next}
    93  }
    94  
    95  func (this *IntIntLinkedMap) ContainsValue(value int32) 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 *IntIntLinkedMap) ContainsKey(key int32) 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 *IntIntLinkedMap) Get(key int32) int32 {
   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 *IntIntLinkedMap) GetFirstKey() int32 {
   137  	this.lock.Lock()
   138  	defer this.lock.Unlock()
   139  
   140  	return this.header.link_next.key
   141  }
   142  
   143  func (this *IntIntLinkedMap) GetLastKey() int32 {
   144  	this.lock.Lock()
   145  	defer this.lock.Unlock()
   146  	return this.header.link_prev.key
   147  }
   148  
   149  func (this *IntIntLinkedMap) GetFirstValue() int32 {
   150  	this.lock.Lock()
   151  	defer this.lock.Unlock()
   152  
   153  	return this.header.link_next.value
   154  }
   155  
   156  func (this *IntIntLinkedMap) GetLastValue() int32 {
   157  	this.lock.Lock()
   158  	defer this.lock.Unlock()
   159  
   160  	return this.header.link_prev.value
   161  }
   162  func (this *IntIntLinkedMap) hash(key int32) uint {
   163  	return uint(key)
   164  }
   165  
   166  func (this *IntIntLinkedMap) rehash() {
   167  	oldCapacity := len(this.table)
   168  	oldMap := this.table
   169  	newCapacity := oldCapacity*2 + 1
   170  	newMap := make([]*IntIntLinkedEntry, newCapacity)
   171  
   172  	this.threshold = int(float32(newCapacity) * this.loadFactor)
   173  	this.table = newMap
   174  	for i := oldCapacity; i > 0; i-- {
   175  		for old := oldMap[i-1]; old != nil; {
   176  			e := old
   177  			old = old.hash_next
   178  			key := e.key
   179  			index := int(this.hash(key) % uint(newCapacity))
   180  			e.hash_next = newMap[index]
   181  			newMap[index] = e
   182  		}
   183  	}
   184  }
   185  
   186  func (this *IntIntLinkedMap) SetMax(max int) *IntIntLinkedMap {
   187  	this.max = max
   188  	return this
   189  }
   190  func (this *IntIntLinkedMap) Put(key int32, value int32) int32 {
   191  	this.lock.Lock()
   192  	defer this.lock.Unlock()
   193  	return this.put(key, value, PUT_LAST)
   194  }
   195  func (this *IntIntLinkedMap) PutLast(key int32, value int32) int32 {
   196  	this.lock.Lock()
   197  	defer this.lock.Unlock()
   198  	return this.put(key, value, PUT_FORCE_LAST)
   199  }
   200  func (this *IntIntLinkedMap) PutFirst(key int32, value int32) int32 {
   201  	this.lock.Lock()
   202  	defer this.lock.Unlock()
   203  	return this.put(key, value, PUT_FORCE_FIRST)
   204  }
   205  func (this *IntIntLinkedMap) put(key int32, value int32, m PUT_MODE) int32 {
   206  
   207  	tab := this.table
   208  	index := this.hash(key) % uint(len(tab))
   209  	for e := tab[index]; e != nil; e = e.hash_next {
   210  		if e.key == key {
   211  			old := e.value
   212  			e.value = value
   213  			switch m {
   214  			case PUT_FORCE_FIRST:
   215  				if this.header.link_next != e {
   216  					this.unchain(e)
   217  					this.chain(this.header, this.header.link_next, e)
   218  				}
   219  			case PUT_FORCE_LAST:
   220  				if this.header.link_prev != e {
   221  					this.unchain(e)
   222  					this.chain(this.header.link_prev, this.header, e)
   223  				}
   224  			}
   225  			return old
   226  		}
   227  	}
   228  	if this.max > 0 {
   229  		switch m {
   230  		case PUT_FORCE_FIRST, PUT_FIRST:
   231  			for this.count >= this.max {
   232  				k := this.header.link_prev.key
   233  				this.remove(k)
   234  			}
   235  		case PUT_FORCE_LAST, PUT_LAST:
   236  			for this.count >= this.max {
   237  				// removeFirst();
   238  				k := this.header.link_next.key
   239  				this.remove(k)
   240  			}
   241  			break
   242  		}
   243  	}
   244  	if this.count >= this.threshold {
   245  		this.rehash()
   246  		tab = this.table
   247  		index = this.hash(key) % uint(len(tab))
   248  	}
   249  	e := &IntIntLinkedEntry{key: key, value: value, hash_next: tab[index]}
   250  	tab[index] = e
   251  	switch m {
   252  	case PUT_FORCE_FIRST, PUT_FIRST:
   253  		this.chain(this.header, this.header.link_next, e)
   254  	case PUT_FORCE_LAST, PUT_LAST:
   255  		this.chain(this.header.link_prev, this.header, e)
   256  	}
   257  	this.count++
   258  	return this.NONE
   259  }
   260  
   261  func (this *IntIntLinkedMap) Add(key int32, value int32) int32 {
   262  	this.lock.Lock()
   263  	defer this.lock.Unlock()
   264  
   265  	return this.add(key, value, PUT_LAST)
   266  }
   267  
   268  func (this *IntIntLinkedMap) AddNoOver(key int32, value int32) int32 {
   269  	this.lock.Lock()
   270  	defer this.lock.Unlock()
   271  
   272  	return this.addNoOver(key, value, PUT_LAST)
   273  }
   274  
   275  func (this *IntIntLinkedMap) AddLast(key int32, value int32) int32 {
   276  	this.lock.Lock()
   277  	defer this.lock.Unlock()
   278  
   279  	return this.add(key, value, PUT_FORCE_LAST)
   280  }
   281  func (this *IntIntLinkedMap) AddFirst(key int32, value int32) int32 {
   282  	this.lock.Lock()
   283  	defer this.lock.Unlock()
   284  
   285  	return this.add(key, value, PUT_FORCE_FIRST)
   286  }
   287  
   288  func (this *IntIntLinkedMap) add(key int32, value int32, m PUT_MODE) int32 {
   289  	tab := this.table
   290  	index := this.hash(key) % uint(len(tab))
   291  	for e := tab[index]; e != nil; e = e.hash_next {
   292  		if e.key == key {
   293  			old := e.value
   294  			e.value += value
   295  			switch m {
   296  			case PUT_FORCE_FIRST:
   297  				if this.header.link_next != e {
   298  					this.unchain(e)
   299  					this.chain(this.header, this.header.link_next, e)
   300  				}
   301  			case PUT_FORCE_LAST:
   302  				if this.header.link_prev != e {
   303  					this.unchain(e)
   304  					this.chain(this.header.link_prev, this.header, e)
   305  				}
   306  			}
   307  			return old
   308  		}
   309  	}
   310  
   311  	if this.max > 0 {
   312  		switch m {
   313  		case PUT_FORCE_FIRST, PUT_FIRST:
   314  			for this.count >= this.max {
   315  				k := this.header.link_prev.key
   316  				this.remove(k)
   317  			}
   318  		case PUT_FORCE_LAST, PUT_LAST:
   319  			for this.count >= this.max {
   320  				k := this.header.link_next.key
   321  				this.remove(k)
   322  			}
   323  			break
   324  		}
   325  	}
   326  
   327  	if this.count >= this.threshold {
   328  		this.rehash()
   329  		tab = this.table
   330  		index = this.hash(key) % uint(len(tab))
   331  	}
   332  	e := &IntIntLinkedEntry{key: key, value: value, hash_next: tab[index]}
   333  	tab[index] = e
   334  	switch m {
   335  	case PUT_FORCE_FIRST, PUT_FIRST:
   336  		this.chain(this.header, this.header.link_next, e)
   337  	case PUT_FORCE_LAST, PUT_LAST:
   338  		this.chain(this.header.link_prev, this.header, e)
   339  	}
   340  	this.count++
   341  	return this.NONE
   342  }
   343  
   344  func (this *IntIntLinkedMap) addNoOver(key int32, value int32, m PUT_MODE) int32 {
   345  	tab := this.table
   346  	index := this.hash(key) % uint(len(tab))
   347  	for e := tab[index]; e != nil; e = e.hash_next {
   348  		if e.key == key {
   349  			old := e.value
   350  			e.value += value
   351  			switch m {
   352  			case PUT_FORCE_FIRST:
   353  				if this.header.link_next != e {
   354  					this.unchain(e)
   355  					this.chain(this.header, this.header.link_next, e)
   356  				}
   357  			case PUT_FORCE_LAST:
   358  				if this.header.link_prev != e {
   359  					this.unchain(e)
   360  					this.chain(this.header.link_prev, this.header, e)
   361  				}
   362  			}
   363  			return old
   364  		}
   365  	}
   366  
   367  	//MAX에 도달하면 더 이상 키를 추가하지 않는다.
   368  	if this.max > 0 && this.count >= this.max {
   369  		return this.NONE
   370  	}
   371  
   372  	if this.count >= this.threshold {
   373  		this.rehash()
   374  		tab = this.table
   375  		index = this.hash(key) % uint(len(tab))
   376  	}
   377  	e := &IntIntLinkedEntry{key: key, value: value, hash_next: tab[index]}
   378  	tab[index] = e
   379  	switch m {
   380  	case PUT_FORCE_FIRST, PUT_FIRST:
   381  		this.chain(this.header, this.header.link_next, e)
   382  	case PUT_FORCE_LAST, PUT_LAST:
   383  		this.chain(this.header.link_prev, this.header, e)
   384  	}
   385  	this.count++
   386  	return this.NONE
   387  }
   388  
   389  func (this *IntIntLinkedMap) Remove(key int32) int32 {
   390  	this.lock.Lock()
   391  	defer this.lock.Unlock()
   392  
   393  	return this.remove(key)
   394  }
   395  func (this *IntIntLinkedMap) RemoveFirst() int32 {
   396  	if this.IsEmpty() {
   397  		return 0
   398  	}
   399  	this.lock.Lock()
   400  	defer this.lock.Unlock()
   401  	return this.remove(this.header.link_next.key)
   402  }
   403  
   404  func (this *IntIntLinkedMap) RemoveLast() int32 {
   405  	if this.IsEmpty() {
   406  		return 0
   407  	}
   408  	this.lock.Lock()
   409  	defer this.lock.Unlock()
   410  	return this.remove(this.header.link_prev.key)
   411  }
   412  
   413  func (this *IntIntLinkedMap) remove(key int32) int32 {
   414  
   415  	tab := this.table
   416  	index := this.hash(key) % uint(len(tab))
   417  	e := tab[index]
   418  	var prev *IntIntLinkedEntry = nil
   419  	for e != nil {
   420  		if e.key == key {
   421  			if prev != nil {
   422  				prev.hash_next = e.hash_next
   423  			} else {
   424  				tab[index] = e.hash_next
   425  			}
   426  			this.count--
   427  			oldValue := e.value
   428  			e.value = this.NONE
   429  			//
   430  			this.unchain(e)
   431  			return oldValue
   432  		}
   433  		prev = e
   434  		e = e.hash_next
   435  	}
   436  	return this.NONE
   437  }
   438  
   439  func (this *IntIntLinkedMap) IsEmpty() bool {
   440  	return this.count == 0
   441  }
   442  func (this *IntIntLinkedMap) IsFull() bool {
   443  	return this.max > 0 && this.max <= this.count
   444  }
   445  
   446  func (this *IntIntLinkedMap) Clear() {
   447  	this.lock.Lock()
   448  	defer this.lock.Unlock()
   449  	this.clear()
   450  }
   451  func (this *IntIntLinkedMap) clear() {
   452  	tab := this.table
   453  	for index := len(tab) - 1; index >= 0; index-- {
   454  		tab[index] = nil
   455  	}
   456  	this.header.link_next = this.header
   457  	this.header.link_prev = this.header
   458  	this.count = 0
   459  }
   460  
   461  func (this *IntIntLinkedMap) chain(link_prev *IntIntLinkedEntry, link_next *IntIntLinkedEntry, e *IntIntLinkedEntry) {
   462  	e.link_prev = link_prev
   463  	e.link_next = link_next
   464  	link_prev.link_next = e
   465  	link_next.link_prev = e
   466  }
   467  
   468  func (this *IntIntLinkedMap) unchain(e *IntIntLinkedEntry) {
   469  	e.link_prev.link_next = e.link_next
   470  	e.link_next.link_prev = e.link_prev
   471  	e.link_prev = nil
   472  	e.link_next = nil
   473  }
   474  
   475  type intIntSortable struct {
   476  	compare func(a, b int32) bool
   477  	data    []*IntIntLinkedEntry
   478  }
   479  
   480  func (this intIntSortable) Len() int {
   481  	return len(this.data)
   482  }
   483  func (this intIntSortable) Less(i, j int) bool {
   484  	return this.compare(this.data[i].GetKey(), this.data[j].GetKey())
   485  }
   486  
   487  func (this intIntSortable) Swap(i, j int) {
   488  	this.data[i], this.data[j] = this.data[j], this.data[i]
   489  }
   490  
   491  func (this *IntIntLinkedMap) Sort(c func(k1, k2 int32) bool) {
   492  	this.lock.Lock()
   493  	defer this.lock.Unlock()
   494  
   495  	sz := this.Size()
   496  	list := make([]*IntIntLinkedEntry, sz)
   497  	en := this.Entries()
   498  	for i := 0; i < sz; i++ {
   499  		list[i] = en.NextElement().(*IntIntLinkedEntry)
   500  	}
   501  	sort.Sort(intIntSortable{compare: c, data: list})
   502  
   503  	this.clear()
   504  	for i := 0; i < sz; i++ {
   505  		this.put(list[i].GetKey(), list[i].GetValue(), PUT_LAST)
   506  	}
   507  }
   508  
   509  func (this *IntIntLinkedMap) ToBytes(dout *io.DataOutputX) {
   510  	dout.WriteDecimal(int64(this.Size()))
   511  	en := this.Entries()
   512  	for en.HasMoreElements() {
   513  		e := en.NextElement().(*IntIntLinkedEntry)
   514  		dout.WriteDecimal(int64(e.GetKey()))
   515  		dout.WriteDecimal(int64(e.GetValue()))
   516  	}
   517  }
   518  
   519  func (this *IntIntLinkedMap) ToObject(din *io.DataInputX) *IntIntLinkedMap {
   520  	cnt := int(din.ReadDecimal())
   521  	for i := 0; i < cnt; i++ {
   522  		key := int32(din.ReadDecimal())
   523  		value := int32(din.ReadDecimal())
   524  		this.Put(key, value)
   525  	}
   526  	return this
   527  }
   528  func (this *IntIntLinkedMap) ToString() string {
   529  	this.lock.Lock()
   530  	defer this.lock.Unlock()
   531  
   532  	var buffer bytes.Buffer
   533  	x := this.Entries()
   534  	buffer.WriteString("{")
   535  	for i := 0; x.HasMoreElements(); i++ {
   536  		if i > 0 {
   537  			buffer.WriteString(", ")
   538  		}
   539  		e := x.NextElement().(*IntIntLinkedEntry)
   540  		buffer.WriteString(e.ToString())
   541  	}
   542  	buffer.WriteString("}")
   543  	return buffer.String()
   544  }