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 }