完成基础的hashmap

This commit is contained in:
eson 2019-04-23 03:05:25 +08:00
parent dd6309456f
commit 0f294d582d
3 changed files with 61 additions and 111 deletions

View File

@ -38,7 +38,7 @@ func New(hcode HashCode, comp compare.Compare) *HashMap {
}
func (hm *HashMap) countNextGrow() {
hm.growsize = hm.table.Cap() << 2
hm.growsize = hm.table.Cap() << 1
}
func (hm *HashMap) grow() {
@ -62,10 +62,10 @@ func (hm *HashMap) grow() {
var hash, index uint
for _, node := range nodelist {
hash = hm.GetHash(node.key)
index = hash % newsize
index = hash % hm.table.cap
//bkt := newtable[index]
bkt := hm.table.GetWithNilSet(index, func(xdata *[4]*avlTree, xindex uint) {
(*xdata)[xindex] = avlNew(hm.Compare)
bkt := hm.table.GetWithNilSet(index, func(data []*avlTree, idx uint) {
data[idx] = avlNew(hm.Compare)
})
bkt.PutNode(node)
}
@ -80,10 +80,9 @@ func (hm *HashMap) Put(key, value interface{}) {
tlen := hm.table.Cap()
index := hash % tlen
bkt := hm.table.GetWithNilSet(index, func(xdata *[4]*avlTree, xindex uint) {
(*xdata)[xindex] = avlNew(hm.Compare)
bkt := hm.table.GetWithNilSet(index, func(data []*avlTree, idx uint) {
data[idx] = avlNew(hm.Compare)
})
if bkt.Put(key, value) {
hm.size++
hm.grow()

View File

@ -1,17 +1,33 @@
package hashmap
import (
"bytes"
"encoding/gob"
"fmt"
"io/ioutil"
"log"
"runtime"
"testing"
"474420502.top/eson/structure/compare"
)
func loadTestData() []int {
log.SetFlags(log.Lshortfile)
data, err := ioutil.ReadFile("../l.log")
if err != nil {
log.Println(err)
}
var l []int
decoder := gob.NewDecoder(bytes.NewReader(data))
decoder.Decode(&l)
return l
}
func TestCount(t *testing.T) {
hm := New(HashInt, compare.Int)
for i := 0; i < 10; i++ {
for i := 0; i < 100000; i++ {
hm.Put(i, i)
}
@ -32,17 +48,42 @@ func bToMb(b uint64) uint64 {
return b / 1024 / 1024
}
var executeCount = 5
var compareSize = 100000
func BenchmarkPut(b *testing.B) {
l := loadTestData()
hm := New(HashInt, compare.Int)
b.N = 100000
for i := 0; i < b.N; i++ {
hm.Put(i, i)
b.N = len(l) * executeCount
for c := 0; c < executeCount; c++ {
for i := 0; i < len(l); i++ {
v := l[i]
hm.Put(v, v)
}
}
//b.Log(len(hm.table), hm.size)
//PrintMemUsage()
}
func BenchmarkGoPut(b *testing.B) {
l := loadTestData()
hm := make(map[int]int)
b.N = len(l) * executeCount
for c := 0; c < executeCount; c++ {
for i := 0; i < len(l); i++ {
v := l[i]
hm[v] = v
}
}
//b.Log(len(m))
//PrintMemUsage()
}
func BenchmarkGet(b *testing.B) {
b.StopTimer()
hm := New(HashInt, compare.Int)
@ -59,16 +100,6 @@ func BenchmarkGet(b *testing.B) {
//PrintMemUsage()
}
func BenchmarkGoPut(b *testing.B) {
m := make(map[int]int)
b.N = 100000
for i := 0; i < b.N; i++ {
m[i] = i
}
//b.Log(len(m))
//PrintMemUsage()
}
func BenchmarkGoGet(b *testing.B) {
b.StopTimer()
m := make(map[int]int)
@ -76,11 +107,6 @@ func BenchmarkGoGet(b *testing.B) {
for i := 0; i < b.N; i++ {
m[i] = i
}
for i := 0; i < b.N; i++ {
if _, ok := m[i]; !ok {
}
}
b.StartTimer()
for i := 0; i < b.N; i++ {
if _, ok := m[i]; !ok {

View File

@ -8,124 +8,49 @@ type Table struct {
size uint
growsize uint
data [][4][4]*avlTree
data []*avlTree
cap uint
}
func newTable() *Table {
table := &Table{}
table.data = make([][4][4]*avlTree, 4, 4)
table.data = make([]*avlTree, 16, 16)
table.countCap()
return table
}
func (t *Table) countCap() {
t.cap = uint(len(t.data)) << 4 // * (4 * 4)
t.cap = uint(len(t.data)) // * (4 * 4)
}
// func (t *Table) countNextGrow() {
// t.growsize = uint(len(t.data)) << 6 // +4 * (4 * 4)
// }
// func (arr *Table) debugValues() []interface{} {
// var result []interface{}
// for _, z := range arr.data {
// if z != nil {
// for _, y := range z {
// if y == nil {
// for i := 0; i < arr.xsize; i++ {
// result = append(result, nil)
// }
// } else {
// for _, x := range y {
// if x == nil {
// result = append(result, struct{}{})
// } else {
// result = append(result, x)
// }
// }
// }
// }
// } else {
// for i := 0; i < arr.ysize*arr.xsize; i++ {
// result = append(result, nil)
// }
// }
// }
// return result
// }
// func (arr *Table) Values() []interface{} {
// var result []interface{}
// for _, z := range arr.data {
// if z != nil {
// for _, y := range z {
// if y == nil {
// for i := 0; i < arr.xsize; i++ {
// result = append(result, nil)
// }
// } else {
// for _, x := range y {
// if x == nil {
// result = append(result, nil)
// } else {
// result = append(result, x)
// }
// }
// }
// }
// } else {
// for i := 0; i < arr.ysize*arr.xsize; i++ {
// result = append(result, nil)
// }
// }
// }
// return result
// }
func (t *Table) Cap() uint {
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)
}
}
every(z)
}
}
func (t *Table) Grow(size int) {
zsize := len(t.data) + size
temp := make([][4][4]*avlTree, zsize, zsize)
temp := make([]*avlTree, zsize, zsize)
copy(temp, t.data)
t.data = temp
t.countCap()
}
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]
return t.data[idx]
}
func (t *Table) GetWithNilSet(idx uint, DoSetValue func(*[4]*avlTree, uint)) *avlTree {
zindex := idx / 16
nidx := (idx % 16)
yindex := nidx / 4
xindex := nidx % 4
func (t *Table) GetWithNilSet(idx uint, DoSetValue func([]*avlTree, uint)) *avlTree {
xdata := t.data[zindex][yindex]
if xdata[xindex] == nil {
DoSetValue(&xdata, xindex)
if t.data[idx] == nil {
DoSetValue(t.data, idx)
}
return xdata[xindex]
return t.data[idx]
}
// func (arr *Table) Get(idx int) (interface{}, bool) {