值不存在
This commit is contained in:
parent
905dcf5f8f
commit
dd6309456f
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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() {
|
||||||
|
@ -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) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user