structure/hashmap/hashmap.go
2019-05-07 13:59:29 +08:00

105 lines
1.9 KiB
Go

package hashmap
import (
"474420502.top/eson/structure/compare"
)
type HashCode func(key interface{}) uint
type HashMap struct {
growfactor uint
slimmingfactor uint
table *Table
GetHash HashCode
Compare compare.Compare
growsize uint
size uint
}
func HashInt(key interface{}) uint {
thekey := uint(key.(int))
hbit := thekey & 0xffffffff
lbit := (thekey & 0xffffffff00000000) >> 32
return lbit ^ hbit
}
func New(hcode HashCode, comp compare.Compare) *HashMap {
hm := &HashMap{}
hm.growfactor = 2
hm.GetHash = hcode
hm.Compare = comp
// initcap := uint(8)
hm.table = newTable()
hm.countNextGrow()
return hm
}
func (hm *HashMap) countNextGrow() {
hm.growsize = hm.table.Cap() << 1
}
func (hm *HashMap) grow() {
if hm.size >= hm.growsize {
newsize := hm.size << 1
// newtable := make([]*avlTree, newsize, newsize)
hm.table.Grow(int(newsize - hm.size))
nodelist := make([]*avlNode, hm.size, hm.size)
i := 0
hm.table.Traversal(func(cur *avlTree) {
if cur != nil {
cur.Traversal(func(node *avlNode) bool {
nodelist[i] = node
i++
return true
})
cur.Clear()
}
})
var hash, index uint
for _, node := range nodelist {
hash = hm.GetHash(node.key)
index = hash % hm.table.cap
//bkt := newtable[index]
bkt := hm.table.GetWithNilSet(index, func(data []*avlTree, idx uint) {
data[idx] = avlNew(hm.Compare)
})
node.clearAttr()
bkt.PutNode(node)
}
hm.countNextGrow()
}
}
func (hm *HashMap) Put(key, value interface{}) {
hash := hm.GetHash(key)
tlen := hm.table.Cap()
index := hash % tlen
bkt := hm.table.GetWithNilSet(index, func(data []*avlTree, idx uint) {
data[idx] = avlNew(hm.Compare)
})
if bkt.Put(key, value) {
hm.size++
hm.grow()
}
}
func (hm *HashMap) Get(key interface{}) (interface{}, bool) {
hash := hm.GetHash(key)
tlen := hm.table.Cap()
index := hash % tlen
bkt := hm.table.Get(index)
if bkt != nil {
return bkt.Get(key)
}
return nil, false
}