完成基础的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() {
|
func (hm *HashMap) countNextGrow() {
|
||||||
hm.growsize = hm.table.Cap() << 2
|
hm.growsize = hm.table.Cap() << 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hm *HashMap) grow() {
|
func (hm *HashMap) grow() {
|
||||||
|
@ -62,10 +62,10 @@ func (hm *HashMap) grow() {
|
||||||
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 % hm.table.cap
|
||||||
//bkt := newtable[index]
|
//bkt := newtable[index]
|
||||||
bkt := hm.table.GetWithNilSet(index, func(xdata *[4]*avlTree, xindex uint) {
|
bkt := hm.table.GetWithNilSet(index, func(data []*avlTree, idx uint) {
|
||||||
(*xdata)[xindex] = avlNew(hm.Compare)
|
data[idx] = avlNew(hm.Compare)
|
||||||
})
|
})
|
||||||
bkt.PutNode(node)
|
bkt.PutNode(node)
|
||||||
}
|
}
|
||||||
|
@ -80,10 +80,9 @@ func (hm *HashMap) Put(key, value interface{}) {
|
||||||
tlen := hm.table.Cap()
|
tlen := hm.table.Cap()
|
||||||
index := hash % tlen
|
index := hash % tlen
|
||||||
|
|
||||||
bkt := hm.table.GetWithNilSet(index, func(xdata *[4]*avlTree, xindex uint) {
|
bkt := hm.table.GetWithNilSet(index, func(data []*avlTree, idx uint) {
|
||||||
(*xdata)[xindex] = avlNew(hm.Compare)
|
data[idx] = avlNew(hm.Compare)
|
||||||
})
|
})
|
||||||
|
|
||||||
if bkt.Put(key, value) {
|
if bkt.Put(key, value) {
|
||||||
hm.size++
|
hm.size++
|
||||||
hm.grow()
|
hm.grow()
|
||||||
|
|
|
@ -1,17 +1,33 @@
|
||||||
package hashmap
|
package hashmap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/gob"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"runtime"
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"474420502.top/eson/structure/compare"
|
"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) {
|
func TestCount(t *testing.T) {
|
||||||
hm := New(HashInt, compare.Int)
|
hm := New(HashInt, compare.Int)
|
||||||
|
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 100000; i++ {
|
||||||
hm.Put(i, i)
|
hm.Put(i, i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,17 +48,42 @@ func bToMb(b uint64) uint64 {
|
||||||
return b / 1024 / 1024
|
return b / 1024 / 1024
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var executeCount = 5
|
||||||
|
var compareSize = 100000
|
||||||
|
|
||||||
func BenchmarkPut(b *testing.B) {
|
func BenchmarkPut(b *testing.B) {
|
||||||
|
l := loadTestData()
|
||||||
|
|
||||||
hm := New(HashInt, compare.Int)
|
hm := New(HashInt, compare.Int)
|
||||||
b.N = 100000
|
b.N = len(l) * executeCount
|
||||||
for i := 0; i < b.N; i++ {
|
for c := 0; c < executeCount; c++ {
|
||||||
hm.Put(i, i)
|
for i := 0; i < len(l); i++ {
|
||||||
|
v := l[i]
|
||||||
|
hm.Put(v, v)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//b.Log(len(hm.table), hm.size)
|
//b.Log(len(hm.table), hm.size)
|
||||||
//PrintMemUsage()
|
//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) {
|
func BenchmarkGet(b *testing.B) {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
hm := New(HashInt, compare.Int)
|
hm := New(HashInt, compare.Int)
|
||||||
|
@ -59,16 +100,6 @@ func BenchmarkGet(b *testing.B) {
|
||||||
//PrintMemUsage()
|
//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) {
|
func BenchmarkGoGet(b *testing.B) {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
m := make(map[int]int)
|
m := make(map[int]int)
|
||||||
|
@ -76,11 +107,6 @@ func BenchmarkGoGet(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
m[i] = i
|
m[i] = i
|
||||||
}
|
}
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if _, ok := m[i]; !ok {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
if _, ok := m[i]; !ok {
|
if _, ok := m[i]; !ok {
|
||||||
|
|
|
@ -8,124 +8,49 @@ type Table struct {
|
||||||
size uint
|
size uint
|
||||||
growsize uint
|
growsize uint
|
||||||
|
|
||||||
data [][4][4]*avlTree
|
data []*avlTree
|
||||||
cap uint
|
cap uint
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTable() *Table {
|
func newTable() *Table {
|
||||||
table := &Table{}
|
table := &Table{}
|
||||||
table.data = make([][4][4]*avlTree, 4, 4)
|
table.data = make([]*avlTree, 16, 16)
|
||||||
table.countCap()
|
table.countCap()
|
||||||
return table
|
return table
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) countCap() {
|
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 {
|
func (t *Table) Cap() uint {
|
||||||
return t.cap
|
return t.cap
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) Traversal(every func(node *avlTree)) {
|
func (t *Table) Traversal(every func(node *avlTree)) {
|
||||||
for _, z := range t.data {
|
for _, z := range t.data {
|
||||||
for _, y := range z {
|
every(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([]*avlTree, zsize, zsize)
|
||||||
copy(temp, t.data)
|
copy(temp, t.data)
|
||||||
t.data = temp
|
t.data = temp
|
||||||
t.countCap()
|
t.countCap()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Table) Get(idx uint) *avlTree {
|
func (t *Table) Get(idx uint) *avlTree {
|
||||||
zindex := idx / 16
|
return t.data[idx]
|
||||||
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 {
|
func (t *Table) GetWithNilSet(idx uint, DoSetValue func([]*avlTree, uint)) *avlTree {
|
||||||
zindex := idx / 16
|
|
||||||
nidx := (idx % 16)
|
|
||||||
yindex := nidx / 4
|
|
||||||
xindex := nidx % 4
|
|
||||||
|
|
||||||
xdata := t.data[zindex][yindex]
|
if t.data[idx] == nil {
|
||||||
if xdata[xindex] == nil {
|
DoSetValue(t.data, idx)
|
||||||
DoSetValue(&xdata, xindex)
|
|
||||||
}
|
}
|
||||||
return xdata[xindex]
|
return t.data[idx]
|
||||||
}
|
}
|
||||||
|
|
||||||
// func (arr *Table) Get(idx int) (interface{}, bool) {
|
// func (arr *Table) Get(idx int) (interface{}, bool) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user