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) { 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 { if err != nil {
log.Println(err) log.Println(err)
} }

View File

@ -2,19 +2,21 @@ package hashmap
import ( import (
"474420502.top/eson/structure/compare" "474420502.top/eson/structure/compare"
"474420502.top/eson/structure/sparse_array/array3"
) )
type HashCode func(key interface{}) uint type HashCode func(key interface{}) uint
type HashMap struct { type HashMap struct {
growfactor uint growfactor uint
table *array3.Array3 slimmingfactor uint
table []interface{}
GetHash HashCode GetHash HashCode
Compare compare.Compare Compare compare.Compare
size uint
growsize uint
size uint
} }
type bNode struct { type bNode struct {
@ -39,47 +41,126 @@ 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
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 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{}) { func (hm *HashMap) Put(key, value interface{}) {
hash := hm.GetHash(key) 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) tlen := uint(len(hm.table))
// cur := bucket.head index := hash % tlen
n := hm.table[index]
// if cur != nil { // if n == nil {
// for cur.Next != nil { // n = avlNew(hm.Compare)
// if hm.Compare(key, cur.Key) == 0 { // hm.table[index] = n
// cur.Key = key
// cur.Value = value
// return
// }
// cur = cur.Next
// }
// } else {
// bucket.head = &bNode{Value: value, Key: key}
// bucket.size++
// hm.size++
// return
// } // }
// bn := &bNode{Value: value, Key: key} // bucket := n.(*avlTree)
// hm.size++ // if bucket.Put(key, value) {
// bucket.size++ // hm.size++
// bn.Next = bucket.head // if hm.size >= hm.growsize {
// bucket.head = bn // newsize := hm.size << 1
// newtable := make([]interface{}, newsize, newsize)
// hm.growsize = newsize - newsize>>2
bucket := n.(*avlTree) // for _, v := range hm.table {
if bucket.Put(key, value) { // 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.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) { func TestCount(t *testing.T) {
hm := New(HashInt, compare.Int) hm := New(HashInt, compare.Int)
for i := 0; i < 1000000; i++ { for i := 0; i < 1000; i++ {
hm.Put(i, i) hm.Put(i, i)
} }
} }
@ -32,18 +32,18 @@ func bToMb(b uint64) uint64 {
func BenchmarkCount(b *testing.B) { func BenchmarkCount(b *testing.B) {
hm := New(HashInt, compare.Int) hm := New(HashInt, compare.Int)
b.N = 10000 b.N = 100000
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
hm.Put(i, i) hm.Put(i, i)
} }
b.Log(hm.table.Cap(), hm.size) b.Log(len(hm.table), hm.size)
PrintMemUsage() PrintMemUsage()
} }
func BenchmarkGoCount(b *testing.B) { func BenchmarkGoCount(b *testing.B) {
m := make(map[int]int) m := make(map[int]int)
b.N = 10000 b.N = 100000
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
m[i] = i m[i] = i
} }