值不存在

This commit is contained in:
eson 2019-04-22 14:06:19 +08:00
parent 905dcf5f8f
commit dd6309456f
3 changed files with 48 additions and 118 deletions

View File

@ -10,7 +10,7 @@ type HashMap struct {
growfactor uint growfactor uint
slimmingfactor uint slimmingfactor uint
table []*avlTree table *Table
GetHash HashCode GetHash HashCode
Compare compare.Compare Compare compare.Compare
@ -19,16 +19,6 @@ type HashMap struct {
size uint size uint
} }
type bNode struct {
Next *bNode
Key, Value interface{}
}
type Bucket struct {
size uint
head *bNode
}
func HashInt(key interface{}) uint { func HashInt(key interface{}) uint {
thekey := uint(key.(int)) thekey := uint(key.(int))
hbit := thekey & 0xffffffff hbit := thekey & 0xffffffff
@ -41,90 +31,45 @@ func New(hcode HashCode, comp compare.Compare) *HashMap {
hm.growfactor = 2 hm.growfactor = 2
hm.GetHash = hcode hm.GetHash = hcode
hm.Compare = comp hm.Compare = comp
initcap := uint(8) // initcap := uint(8)
hm.table = make([]*avlTree, initcap, initcap) hm.table = newTable()
hm.countNextGrow() hm.countNextGrow()
return hm return hm
} }
// func (hm *HashMap) grow() {
// if hm.size >= hm.growsize {
// newsize := hm.size << 1
// newtable := make([]*Bucket, newsize, newsize)
// hm.growsize = newsize - newsize>>2
// for _, bucket := range hm.table {
// if bucket != nil {
// cur := bucket.head
// hash := hm.GetHash(cur.Key)
// index := hash % newsize
// // var bkt *Bucket
// bkt := newtable[index]
// if bkt == nil {
// bkt = &Bucket{size: 1}
// newtable[index] = bkt
// bkt.head = &bNode{Value: cur.Value, Key: cur.Key}
// cur = cur.Next
// }
// for ; cur != nil; cur = cur.Next {
// bn := &bNode{Value: cur.Value, Key: cur.Key}
// bkt.size++
// bn.Next = bkt.head
// bkt.head = bn
// }
// }
// hm.table = newtable
// }
// }
// }
func (hm *HashMap) countNextGrow() { func (hm *HashMap) countNextGrow() {
hm.growsize = uint(len(hm.table)) << 2 hm.growsize = hm.table.Cap() << 2
} }
func (hm *HashMap) grow() { func (hm *HashMap) grow() {
if hm.size >= hm.growsize { if hm.size >= hm.growsize {
newsize := hm.size << 1 newsize := hm.size << 1
newtable := make([]*avlTree, newsize, newsize) // newtable := make([]*avlTree, newsize, newsize)
hm.table.Grow(int(newsize - hm.size))
nodelist := make([]*avlNode, hm.size, hm.size) nodelist := make([]*avlNode, hm.size, hm.size)
i := 0 i := 0
for _, cur := range hm.table { hm.table.Traversal(func(cur *avlTree) {
if cur != nil { if cur != nil {
cur.Traversal(func(node *avlNode) bool { cur.Traversal(func(node *avlNode) bool {
nodelist[i] = node nodelist[i] = node
i++ i++
// hash := hm.GetHash(node.key)
// index := hash % newsize
// bkt := newtable[index]
// if bkt == nil {
// bkt = avlNew(hm.Compare)
// newtable[index] = bkt
// }
//bkt.Put(node.key, node.value)
return true return true
}) })
}
cur.Clear() cur.Clear()
} }
})
var hash, index uint var hash, index uint
for _, node := range nodelist { for _, node := range nodelist {
hash = hm.GetHash(node.key) hash = hm.GetHash(node.key)
index = hash % newsize index = hash % newsize
bkt := newtable[index] //bkt := newtable[index]
if bkt == nil { bkt := hm.table.GetWithNilSet(index, func(xdata *[4]*avlTree, xindex uint) {
bkt = avlNew(hm.Compare) (*xdata)[xindex] = avlNew(hm.Compare)
newtable[index] = bkt })
}
bkt.PutNode(node) bkt.PutNode(node)
} }
hm.table = newtable
hm.countNextGrow() hm.countNextGrow()
} }
} }
@ -132,60 +77,28 @@ func (hm *HashMap) grow() {
func (hm *HashMap) Put(key, value interface{}) { func (hm *HashMap) Put(key, value interface{}) {
hash := hm.GetHash(key) hash := hm.GetHash(key)
tlen := uint(len(hm.table)) tlen := hm.table.Cap()
index := hash % tlen index := hash % tlen
bkt := hm.table[index]
if bkt == nil { bkt := hm.table.GetWithNilSet(index, func(xdata *[4]*avlTree, xindex uint) {
bkt = avlNew(hm.Compare) (*xdata)[xindex] = avlNew(hm.Compare)
hm.table[index] = bkt })
}
if bkt.Put(key, value) { if bkt.Put(key, value) {
hm.size++ hm.size++
hm.grow() hm.grow()
} }
// if bkt == nil {
// nbucket := &Bucket{size: 1}
// hm.table[index] = nbucket
// nbucket.head = &bNode{Value: value, Key: key}
// hm.size++
// hm.grow()
// return
// }
// cur := bkt.head
// for cur.Next != nil {
// if hm.Compare(key, cur.Key) == 0 {
// cur.Key = key
// cur.Value = value
// return
// }
// cur = cur.Next
// }
// bn := &bNode{Value: value, Key: key}
// hm.size++
// bkt.size++
// bn.Next = bkt.head
// bkt.head = bn
// hm.grow()
} }
func (hm *HashMap) Get(key interface{}) (interface{}, bool) { func (hm *HashMap) Get(key interface{}) (interface{}, bool) {
hash := hm.GetHash(key) hash := hm.GetHash(key)
tlen := uint(len(hm.table)) tlen := hm.table.Cap()
index := hash % tlen index := hash % tlen
bkt := hm.table[index]
bkt := hm.table.Get(index)
if bkt != nil { if bkt != nil {
return bkt.Get(key) return bkt.Get(key)
} }
return nil, false return nil, false
} }

View File

@ -11,9 +11,11 @@ import (
func TestCount(t *testing.T) { func TestCount(t *testing.T) {
hm := New(HashInt, compare.Int) hm := New(HashInt, compare.Int)
for i := 0; i < 1000; i++ { for i := 0; i < 10; i++ {
hm.Put(i, i) hm.Put(i, i)
} }
t.Error(hm.Get(4))
} }
func PrintMemUsage() { func PrintMemUsage() {

View File

@ -89,6 +89,16 @@ func (t *Table) Cap() uint {
return t.cap return t.cap
} }
func (t *Table) Traversal(every func(node *avlTree)) {
for _, z := range t.data {
for _, y := range z {
for _, x := range y {
every(x)
}
}
}
}
func (t *Table) Grow(size int) { func (t *Table) Grow(size int) {
zsize := len(t.data) + size zsize := len(t.data) + size
temp := make([][4][4]*avlTree, zsize, zsize) temp := make([][4][4]*avlTree, zsize, zsize)
@ -97,20 +107,25 @@ func (t *Table) Grow(size int) {
t.countCap() t.countCap()
} }
func (t *Table) GetWithNilSet(idx int, DoSetValue func([4]*avlTree, int)) *avlTree { func (t *Table) Get(idx uint) *avlTree {
zindex := idx / 16
nidx := (idx % 16)
yindex := nidx / 4
xindex := nidx % 4
return t.data[zindex][yindex][xindex]
}
func (t *Table) GetWithNilSet(idx uint, DoSetValue func(*[4]*avlTree, uint)) *avlTree {
zindex := idx / 16 zindex := idx / 16
nidx := (idx % 16) nidx := (idx % 16)
yindex := nidx / 4 yindex := nidx / 4
xindex := nidx % 4 xindex := nidx % 4
ydata := t.data[zindex] xdata := t.data[zindex][yindex]
xdata := ydata[yindex] if xdata[xindex] == nil {
DoSetValue(&xdata, xindex)
v := xdata[xindex]
if v == nil {
DoSetValue(xdata, xindex)
} }
return v return xdata[xindex]
} }
// func (arr *Table) Get(idx int) (interface{}, bool) { // func (arr *Table) Get(idx int) (interface{}, bool) {