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

     1  package hmap
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  
     7  	"github.com/whatap/golib/util/hash"
     8  )
     9  
    10  // TODO SearchPathMap 에서 사용하기 위해 생성 (현재는 생성만)
    11  // 테스트 필요.
    12  type StringSet struct {
    13  	table      []*StringSetry
    14  	count      int
    15  	threshold  int
    16  	loadFactor float32
    17  	lock       sync.Mutex
    18  	max        int
    19  }
    20  
    21  func NewStringSet() *StringSet {
    22  
    23  	initCapacity := DEFAULT_CAPACITY
    24  	loadFactor := DEFAULT_LOAD_FACTOR
    25  
    26  	this := new(StringSet)
    27  	this.loadFactor = float32(loadFactor)
    28  	this.table = make([]*StringSetry, initCapacity)
    29  	this.threshold = int(float64(initCapacity) * loadFactor)
    30  	return this
    31  }
    32  
    33  func NewStringSetArray(arr []string) *StringSet {
    34  
    35  	initCapacity := DEFAULT_CAPACITY
    36  	loadFactor := DEFAULT_LOAD_FACTOR
    37  
    38  	this := new(StringSet)
    39  	this.loadFactor = float32(loadFactor)
    40  	this.table = make([]*StringSetry, initCapacity)
    41  	this.threshold = int(float64(initCapacity) * loadFactor)
    42  	return this
    43  }
    44  
    45  func (this *StringSet) Size() int {
    46  	return this.count
    47  }
    48  
    49  func (this *StringSet) Keys() StringEnumer {
    50  	return &StringSetEnumer{table: this.table, index: len(this.table), entry: nil}
    51  }
    52  
    53  func (this *StringSet) HasKey(key string) bool {
    54  	return this.Contains(key)
    55  }
    56  
    57  func (this *StringSet) Contains(key string) bool {
    58  	this.lock.Lock()
    59  	defer this.lock.Unlock()
    60  	if key == "" {
    61  		return false
    62  	}
    63  
    64  	tab := this.table
    65  	index := this.hash(key) % uint(len(tab))
    66  	for e := tab[index]; e != nil; e = e.next {
    67  		if e.key == key {
    68  			return true
    69  		}
    70  	}
    71  	return false
    72  }
    73  
    74  func (this *StringSet) rehash() {
    75  	oldCapacity := len(this.table)
    76  	oldMap := this.table
    77  	newCapacity := oldCapacity*2 + 1
    78  	newMap := make([]*StringSetry, newCapacity)
    79  	this.threshold = int(float32(newCapacity) * this.loadFactor)
    80  	this.table = newMap
    81  	for i := oldCapacity; i > 0; i-- {
    82  		for old := oldMap[i-1]; old != nil; {
    83  			e := old
    84  			old = old.next
    85  			index := uint(this.hash(e.key) % uint(newCapacity))
    86  			e.next = newMap[index]
    87  			newMap[index] = e
    88  		}
    89  	}
    90  }
    91  
    92  func (this *StringSet) Put(key string) string {
    93  	this.lock.Lock()
    94  	defer this.lock.Unlock()
    95  	return this.unipoint(key)
    96  }
    97  
    98  func (this *StringSet) Unipoint(key string) string {
    99  	this.lock.Lock()
   100  	defer this.lock.Unlock()
   101  	return this.unipoint(key)
   102  }
   103  
   104  func (this *StringSet) unipoint(key string) string {
   105  	if key == "" {
   106  		return ""
   107  	}
   108  	tab := this.table
   109  	hash := this.hash(key)
   110  	index := hash % uint(len(tab))
   111  	for e := tab[index]; e != nil; e = e.next {
   112  		if e.key == key {
   113  			return e.key
   114  		}
   115  	}
   116  	if this.count >= this.threshold {
   117  		this.rehash()
   118  		tab = this.table
   119  		index = hash % uint(len(tab))
   120  	}
   121  	e := &StringSetry{hash: hash, key: key, next: tab[index]}
   122  	tab[index] = e
   123  	this.count++
   124  	return key
   125  }
   126  
   127  func (this *StringSet) Remove(key string) bool {
   128  	this.lock.Lock()
   129  	defer this.lock.Unlock()
   130  
   131  	return this.remove(key)
   132  }
   133  
   134  func (this *StringSet) remove(key string) bool {
   135  	if key == "" {
   136  		return false
   137  	}
   138  	tab := this.table
   139  	index := this.hash(key) % uint(len(tab))
   140  	e := tab[index]
   141  	var prev *StringSetry = nil
   142  	for e != nil {
   143  		if e.key == key {
   144  			if prev != nil {
   145  				prev.next = e.next
   146  			} else {
   147  				tab[index] = e.next
   148  			}
   149  			this.count--
   150  			return true
   151  		}
   152  		prev = e
   153  		e = e.next
   154  	}
   155  	return false
   156  }
   157  
   158  func (this *StringSet) Clear() {
   159  	this.lock.Lock()
   160  	defer this.lock.Unlock()
   161  	this.clear()
   162  }
   163  func (this *StringSet) clear() {
   164  	tab := this.table
   165  	for index := len(tab) - 1; index >= 0; index-- {
   166  		tab[index] = nil
   167  	}
   168  	this.count = 0
   169  }
   170  
   171  func (this *StringSet) hash(key string) uint {
   172  	return uint(hash.HashStr(key))
   173  }
   174  
   175  type StringSetEnumer struct {
   176  	table []*StringSetry
   177  	index int
   178  	entry *StringSetry
   179  }
   180  
   181  func NewStringSetEnumer(table []*StringSetry, index int) {
   182  	p := new(StringSetEnumer)
   183  	p.table = table
   184  	p.index = len(table)
   185  	p.entry = nil
   186  }
   187  func (this *StringSetEnumer) HasMoreElements() bool {
   188  	for this.entry == nil && this.index > 0 {
   189  		this.index--
   190  		this.entry = this.table[this.index]
   191  	}
   192  	return this.entry != nil
   193  }
   194  
   195  func (this *StringSetEnumer) NextString() string {
   196  	for this.entry == nil && this.index > 0 {
   197  		this.index--
   198  		this.entry = this.table[this.index]
   199  	}
   200  	if this.entry != nil {
   201  		e := this.entry
   202  		this.entry = e.next
   203  		return e.key
   204  	}
   205  	//panic("no more next")
   206  	return ""
   207  }
   208  
   209  func StringSetMain() {
   210  	s := NewStringSet()
   211  	s.Put("aa")
   212  	s.Put("bb")
   213  	s.Put("00")
   214  	//	s.Sort(c func(k1, k2 string) bool)
   215  	fmt.Println(s)
   216  	//	s.Sort(false)
   217  	fmt.Println(s)
   218  }