hashmap so bad

This commit is contained in:
eson 2019-04-21 13:31:39 +08:00
parent 5f47199d08
commit 36743be520
3 changed files with 121 additions and 40 deletions

View File

@ -16,7 +16,7 @@ const NumberMax = 50000000
func TestSave(t *testing.T) {
f, err := os.OpenFile("../l.log", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
f, err := os.OpenFile("l.log", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
if err != nil {
log.Println(err)
}

View File

@ -2,19 +2,21 @@ package hashmap
import (
"474420502.top/eson/structure/compare"
"474420502.top/eson/structure/sparse_array/array3"
)
type HashCode func(key interface{}) uint
type HashMap struct {
growfactor uint
table *array3.Array3
growfactor uint
slimmingfactor uint
table []interface{}
GetHash HashCode
Compare compare.Compare
size uint
growsize uint
size uint
}
type bNode struct {
@ -39,47 +41,126 @@ func New(hcode HashCode, comp compare.Compare) *HashMap {
hm.growfactor = 2
hm.GetHash = hcode
hm.Compare = comp
hm.table = array3.NewWithCap(hm.growfactor<<2, hm.growfactor<<2, hm.growfactor<<2)
initcap := uint(8)
hm.table = make([]interface{}, initcap, initcap)
hm.growsize = initcap - initcap>>2
return hm
}
func (hm *HashMap) grow() {
if hm.size >= hm.growsize {
newsize := hm.size << 1
newtable := make([]interface{}, newsize, newsize)
hm.growsize = newsize - newsize>>2
hm.size = 0
for _, v := range hm.table {
if v != nil {
bucket := v.(*Bucket)
cur := bucket.head
hash := hm.GetHash(cur.Key)
index := hash % newsize
var bkt *Bucket
n := newtable[index]
if n == nil {
bkt = &Bucket{size: 1}
newtable[index] = bkt
bkt.head = &bNode{Value: cur.Value, Key: cur.Key}
hm.size++
cur = cur.Next
} else {
bkt = n.(*Bucket)
}
for ; cur != nil; cur = cur.Next {
bn := &bNode{Value: cur.Value, Key: cur.Key}
hm.size++
bkt.size++
bn.Next = bkt.head
bkt.head = bn
}
}
hm.table = newtable
}
}
}
func (hm *HashMap) Put(key, value interface{}) {
hash := hm.GetHash(key)
// log.Println(hm.table.Cap())
index := hash % hm.table.Cap()
n, _ := hm.table.GetOrSet(index, func(data []interface{}, index uint) {
data[index] = avlNew(hm.Compare)
// data[index] = &Bucket{}
})
// bucket := n.(*Bucket)
// cur := bucket.head
tlen := uint(len(hm.table))
index := hash % tlen
n := hm.table[index]
// if cur != nil {
// for cur.Next != nil {
// if hm.Compare(key, cur.Key) == 0 {
// cur.Key = key
// cur.Value = value
// return
// }
// cur = cur.Next
// }
// } else {
// bucket.head = &bNode{Value: value, Key: key}
// bucket.size++
// hm.size++
// return
// if n == nil {
// n = avlNew(hm.Compare)
// hm.table[index] = n
// }
// bn := &bNode{Value: value, Key: key}
// hm.size++
// bucket.size++
// bucket := n.(*avlTree)
// if bucket.Put(key, value) {
// hm.size++
// bn.Next = bucket.head
// bucket.head = bn
// if hm.size >= hm.growsize {
// newsize := hm.size << 1
// newtable := make([]interface{}, newsize, newsize)
// hm.growsize = newsize - newsize>>2
bucket := n.(*avlTree)
if bucket.Put(key, value) {
// for _, v := range hm.table {
// if v != nil {
// cur := v.(*avlTree)
// cur.Traversal(func(k, v interface{}) bool {
// hash := hm.GetHash(k)
// index := hash % newsize
// n := newtable[index]
// if n == nil {
// n = avlNew(hm.Compare)
// newtable[index] = n
// }
// bucket := n.(*avlTree)
// bucket.Put(k, v)
// return true
// })
// }
// }
// hm.table = newtable
// }
// }
if n == nil {
nbucket := &Bucket{size: 1}
hm.table[index] = nbucket
nbucket.head = &bNode{Value: value, Key: key}
hm.size++
hm.grow()
return
}
bkt := n.(*Bucket)
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()
}

View File

@ -11,7 +11,7 @@ import (
func TestCount(t *testing.T) {
hm := New(HashInt, compare.Int)
for i := 0; i < 1000000; i++ {
for i := 0; i < 1000; i++ {
hm.Put(i, i)
}
}
@ -32,18 +32,18 @@ func bToMb(b uint64) uint64 {
func BenchmarkCount(b *testing.B) {
hm := New(HashInt, compare.Int)
b.N = 10000
b.N = 100000
for i := 0; i < b.N; i++ {
hm.Put(i, i)
}
b.Log(hm.table.Cap(), hm.size)
b.Log(len(hm.table), hm.size)
PrintMemUsage()
}
func BenchmarkGoCount(b *testing.B) {
m := make(map[int]int)
b.N = 10000
b.N = 100000
for i := 0; i < b.N; i++ {
m[i] = i
}