From ef40597c46de00f0d8859afddaeb6e0e45b36f44 Mon Sep 17 00:00:00 2001 From: zhanghuiren Date: Sun, 24 Nov 2019 02:15:59 +0800 Subject: [PATCH 1/2] mapx --- mapx/hash_map.go | 44 ++++++++++++++++++++++++++++++++++++++++++ mapx/map.go | 10 ++++++++++ mapx/map_test.go | 44 ++++++++++++++++++++++++++++++++++++++++++ mapx/slice_map_test.go | 1 + mapx/sync_map.go | 24 +++++++++++++++++++++++ 5 files changed, 123 insertions(+) create mode 100644 mapx/hash_map.go create mode 100644 mapx/map.go create mode 100644 mapx/map_test.go create mode 100644 mapx/slice_map_test.go create mode 100644 mapx/sync_map.go diff --git a/mapx/hash_map.go b/mapx/hash_map.go new file mode 100644 index 0000000..eea43e2 --- /dev/null +++ b/mapx/hash_map.go @@ -0,0 +1,44 @@ +package mapx + +var _ MapInterface = &HashMap{} + +type HashMap map[interface{}]interface{} + +func MakeHashMap(size int) HashMap { + return make(HashMap, size) +} +func (m HashMap) Load(key interface{}) (value interface{}, exist bool) { + value, exist = m[key] + return +} + +func (m HashMap) Store(key, value interface{}) { + m[key] = value +} + +func (m HashMap) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool) { + actual, exist := m.Load(key) + if exist { + return actual, true + } + + m.Store(key, value) + return value, false +} + +func (m HashMap) Delete(key interface{}) { + delete(m, key) +} + +func (m HashMap) Range(f func(key, value interface{}) (shouldContinue bool)) { + for k, v := range m { + shouldContinue := f(k, v) + if !shouldContinue { + break + } + } +} + +func (m HashMap) Len() (length int) { + return len(m) +} diff --git a/mapx/map.go b/mapx/map.go new file mode 100644 index 0000000..43a78c4 --- /dev/null +++ b/mapx/map.go @@ -0,0 +1,10 @@ +package mapx + +type MapInterface interface { + Load(interface{}) (interface{}, bool) + Store(key, value interface{}) + LoadOrStore(key, value interface{}) (actual interface{}, loaded bool) + Delete(interface{}) + Range(func(key, value interface{}) (shouldContinue bool)) + Len() int +} diff --git a/mapx/map_test.go b/mapx/map_test.go new file mode 100644 index 0000000..935112e --- /dev/null +++ b/mapx/map_test.go @@ -0,0 +1,44 @@ +package mapx + +import ( + "fmt" + "testing" +) + +var size = 8 +var m = MakeHashMap(size) +var s = MakeSliceMap(size) +var name = make([]string, size) + +func TestMain(tm *testing.M) { + for i := 0; i < size; i++ { + m.Store(i%size, i+1) + s.Store(i%size, i+1) + name[i%size] = fmt.Sprint(i + 1) + } + tm.Run() +} + +func BenchmarkMapLoad(b *testing.B) { + for i := 0; i < b.N; i++ { + m.Load(name[i%size]) + } +} + +func BenchmarkSliceLoad(b *testing.B) { + for i := 0; i < b.N; i++ { + s.Load(name[i%size]) + } +} + +func BenchmarkMapStore(b *testing.B) { + for i := 0; i < b.N; i++ { + m.Store(name[i%size], i%size) + } +} + +func BenchmarkSliceStore(b *testing.B) { + for i := 0; i < b.N; i++ { + s.Store(name[i%size], i%size) + } +} diff --git a/mapx/slice_map_test.go b/mapx/slice_map_test.go new file mode 100644 index 0000000..3dbf138 --- /dev/null +++ b/mapx/slice_map_test.go @@ -0,0 +1 @@ +package mapx diff --git a/mapx/sync_map.go b/mapx/sync_map.go new file mode 100644 index 0000000..1b94e9e --- /dev/null +++ b/mapx/sync_map.go @@ -0,0 +1,24 @@ +package mapx + +import ( + "sync" +) + +var _ MapInterface = &SyncMap{} + +type SyncMap struct { + sync.Map +} + +func MakeSyncMap(size int) *SyncMap { + return &SyncMap{} +} + +func (m *SyncMap) Len() (length int) { + length = 0 + m.Range(func(key, value interface{}) (shouldContinue bool) { + length++ + return true + }) + return +} From e89c480112b9929a62edb9e26e6628b4ce1eb301 Mon Sep 17 00:00:00 2001 From: zhanghuiren Date: Sun, 24 Nov 2019 02:20:27 +0800 Subject: [PATCH 2/2] commit slice map --- mapx/slice_map.go | 93 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/mapx/slice_map.go b/mapx/slice_map.go index 3dbf138..abe73ba 100644 --- a/mapx/slice_map.go +++ b/mapx/slice_map.go @@ -1 +1,94 @@ package mapx + +var _ MapInterface = &SliceMap{} + +type sliceElem struct { + key interface{} + value interface{} + + deleted bool +} + +func (e *sliceElem) isAlive() bool { + return !e.deleted +} + +type SliceMap []*sliceElem + +func MakeSliceMap(size int) *SliceMap { + slice := make(SliceMap, 0, size) + return &slice +} + +func (m SliceMap) Load(k interface{}) (v interface{}, exist bool) { + //for i := len(m) - 1; i >= 0; i-- { + // e := m[i] + for _, e := range m { + if e.isAlive() && keyEqual(e.key, k) { + return e.value, true + } + } + return nil, false +} + +func (m *SliceMap) Store(key, value interface{}) { + //for i := len(*m) - 1; i >= 0; i-- { + // e := (*m)[i] + for _, e := range *m { + if keyEqual(e.key, key) { + e.value = value + e.deleted = false + return + } + } + + *m = append(*m, &sliceElem{key, value, false}) +} + +func (m *SliceMap) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool) { + for _, e := range *m { + if keyEqual(e.key, key) { + if e.isAlive() { + return e.value, true + } + + e.value = value + e.deleted = false + return e.value, false + } + } + + *m = append(*m, &sliceElem{key, value, false}) + + return value, false +} + +func (m SliceMap) Delete(key interface{}) { + for _, e := range m { + if keyEqual(e.key, key) { + e.deleted = true + return + } + } +} + +func (m SliceMap) Range(f func(key, value interface{}) (shouldContinue bool)) { + for _, e := range m { + if !e.isAlive() { + continue + } + + shouldContinue := f(e.key, e.value) + if !shouldContinue { + break + } + } +} + +func (m SliceMap) Len() int { + return len(m) +} + +func keyEqual(a, b interface{}) bool { + return a == b +}