完成基础的hashmap
This commit is contained in:
parent
dd6309456f
commit
0f294d582d
|
@ -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()
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user