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

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