From 278c8b4cb720d48901d155ee2631976fbc5bfd39 Mon Sep 17 00:00:00 2001 From: charlie <3140647@qq.com> Date: Fri, 18 Nov 2022 16:57:15 +0800 Subject: [PATCH] maps --- maps/concurrent_map.go | 44 ++++++----------------- maps/hash_map.go | 7 ++-- maps/hash_map_test.go | 5 +++ maps/haxmap.go | 81 ++++++++++++++++++++++++++++++++++++++++++ maps/map.go | 18 +++++----- maps/rwlock_map.go | 33 +++++------------ maps/sort_map.go | 21 ++++------- 7 files changed, 124 insertions(+), 85 deletions(-) create mode 100644 maps/haxmap.go diff --git a/maps/concurrent_map.go b/maps/concurrent_map.go index 0ceab77..8aa7d24 100644 --- a/maps/concurrent_map.go +++ b/maps/concurrent_map.go @@ -7,17 +7,16 @@ import ( "github.com/charlienet/go-mixed/bytesconv" "github.com/charlienet/go-mixed/hash" - "golang.org/x/exp/constraints" ) var defaultNumOfBuckets = runtime.GOMAXPROCS(runtime.NumCPU()) -type concurrnetMap[K constraints.Ordered, V any] struct { +type concurrnetMap[K hashable, V any] struct { buckets []Map[K, V] numOfBuckets uint64 } -func NewConcurrentMap[K constraints.Ordered, V any](maps ...map[K]V) *concurrnetMap[K, V] { +func NewConcurrentMap[K hashable, V any](maps ...map[K]V) *concurrnetMap[K, V] { num := defaultNumOfBuckets buckets := make([]Map[K, V], num) @@ -57,16 +56,16 @@ func (m *concurrnetMap[K, V]) Exist(key K) bool { return mm.Exist(key) } -func (m *concurrnetMap[K, V]) Iter() <-chan *Entry[K, V] { - num := int(m.numOfBuckets) - ch := make(chan *Entry[K, V], m.Count()) - for i := 0; i < num; i++ { - c := m.buckets[i].Iter() - ch <- <-c - } +// func (m *concurrnetMap[K, V]) Iter() <-chan *Entry[K, V] { +// num := int(m.numOfBuckets) +// ch := make(chan *Entry[K, V], m.Count()) +// for i := 0; i < num; i++ { +// c := m.buckets[i].Iter() +// ch <- <-c +// } - return ch -} +// return ch +// } func (m *concurrnetMap[K, V]) Keys() []K { keys := make([]K, m.Count()) @@ -111,27 +110,6 @@ func (m *concurrnetMap[K, V]) ForEach(f func(K, V) bool) { wg.Wait() } -func (m *concurrnetMap[K, V]) Clone() Map[K, V] { - - num := int(m.numOfBuckets) - - buckets := make([]Map[K, V], m.numOfBuckets) - for i := 0; i < num; i++ { - buckets[i] = m.buckets[i].Clone() - } - - return &concurrnetMap[K, V]{ - buckets: buckets, - numOfBuckets: m.numOfBuckets, - } -} - -func (m *concurrnetMap[K, V]) Clear() { - for i := 0; i < int(m.numOfBuckets); i++ { - m.buckets[i].Clear() - } -} - func (m *concurrnetMap[K, V]) Count() int { var count int for i := 0; i < int(m.numOfBuckets); i++ { diff --git a/maps/hash_map.go b/maps/hash_map.go index 79bcc81..025f75a 100644 --- a/maps/hash_map.go +++ b/maps/hash_map.go @@ -2,15 +2,14 @@ package maps import ( "github.com/charlienet/go-mixed/locker" - "golang.org/x/exp/constraints" ) -type hashMap[K constraints.Ordered, V any] struct { +type hashMap[K hashable, V any] struct { m map[K]V opt *options } -func NewHashMap[K constraints.Ordered, V any](maps ...map[K]V) *hashMap[K, V] { +func NewHashMap[K hashable, V any](maps ...map[K]V) *hashMap[K, V] { m := make(map[K]V) if len(maps) > 0 { m = Merge(maps...) @@ -74,7 +73,7 @@ func (m *hashMap[K, V]) Iter() <-chan *Entry[K, V] { return ch } -func (m *hashMap[K, V]) ForEach(f func(K, V) bool ) { +func (m *hashMap[K, V]) ForEach(f func(K, V) bool) { cloned := m.ToMap() for k, v := range cloned { diff --git a/maps/hash_map_test.go b/maps/hash_map_test.go index 2a60c4a..02229aa 100644 --- a/maps/hash_map_test.go +++ b/maps/hash_map_test.go @@ -25,3 +25,8 @@ func TestForEach(t *testing.T) { assert.True(t, hashMap.Exist(k)) } } + +func TestSynchronize(t *testing.T) { + mep := NewHashMap[string, string]().Synchronize() + mep.Set("aaaa", "bbb") +} diff --git a/maps/haxmap.go b/maps/haxmap.go new file mode 100644 index 0000000..665f494 --- /dev/null +++ b/maps/haxmap.go @@ -0,0 +1,81 @@ +package maps + +import ( + "github.com/alphadose/haxmap" +) + +type haxHashable interface { + int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | uintptr | float32 | float64 | string | complex64 | complex128 +} + +var _ Map[string, string] = &haxmapWrapper[string, string]{} + +type haxmapWrapper[K haxHashable, V any] struct { + mep *haxmap.Map[K, V] +} + +func NewHaxmap[K haxHashable, V any](size int) *haxmapWrapper[K, V] { + return &haxmapWrapper[K, V]{ + mep: haxmap.New[K, V](uintptr(size)), + } +} + +func (m *haxmapWrapper[K, V]) Set(k K, v V) { + m.mep.Set(k, v) +} + +func (m *haxmapWrapper[K, V]) Get(k K) (V, bool) { + return m.mep.Get(k) +} + +func (m *haxmapWrapper[K, V]) Keys() []K { + keys := make([]K, 0, m.mep.Len()) + m.mep.ForEach(func(k K, v V) bool { + keys = append(keys, k) + + return true + }) + + return keys +} + +func (m *haxmapWrapper[K, V]) Values() []V { + values := make([]V, 0, m.mep.Len()) + m.mep.ForEach(func(k K, v V) bool { + values = append(values, v) + + return true + }) + + return values +} + +func (m *haxmapWrapper[K, V]) Exist(k K) bool { + return false +} + +func (m *haxmapWrapper[K, V]) Delete(key K) { + m.mep.Del(key) +} + +func (m *haxmapWrapper[K, V]) ToMap() map[K]V { + mm := make(map[K]V, m.mep.Len()) + m.mep.ForEach(func(k K, v V) bool { + mm[k] = v + + return true + }) + + return mm +} + +func (m *haxmapWrapper[K, V]) ForEach(fn func(K, V) bool) { + +} + +func (m *haxmapWrapper[K, V]) Count() int { + return int(m.mep.Len()) +} + +func (m *haxmapWrapper[K, V]) Clear() { +} diff --git a/maps/map.go b/maps/map.go index b29b77a..4e97125 100644 --- a/maps/map.go +++ b/maps/map.go @@ -6,7 +6,11 @@ import ( "golang.org/x/exp/constraints" ) -type Map[K constraints.Ordered, V any] interface { +type hashable interface { + constraints.Integer | constraints.Float | ~string +} + +type Map[K hashable, V any] interface { Set(key K, value V) // 设置值 Get(key K) (value V, ok bool) // 获取值 Exist(key K) bool // 键是否存在 @@ -14,19 +18,17 @@ type Map[K constraints.Ordered, V any] interface { Keys() []K // 获取所有键 Values() []V // 获取所有值 ToMap() map[K]V // 转换为map - Clone() Map[K, V] // 复制 - Clear() // 清空 Count() int // 数量 - Iter() <-chan *Entry[K, V] // 迭代器 - ForEach(f func(K, V) bool) // ForEach + // Iter() <-chan *Entry[K, V] // 迭代器 + ForEach(f func(K, V) bool) // ForEach } -type Entry[K constraints.Ordered, V any] struct { +type Entry[K hashable, V any] struct { Key K Value V } -func Merge[K comparable, V any](mm ...map[K]V) map[K]V { +func Merge[K hashable, V any](mm ...map[K]V) map[K]V { ret := make(map[K]V) for _, m := range mm { for k, v := range m { @@ -38,7 +40,7 @@ func Merge[K comparable, V any](mm ...map[K]V) map[K]V { } // 按照键值生成字符串 -func Join[K constraints.Ordered, V any](m Map[K, V], sep string, f func(k K, v V) string) string { +func Join[K hashable, V any](m Map[K, V], sep string, f func(k K, v V) string) string { slice := make([]string, 0, m.Count()) m.ForEach(func(k K, v V) bool { diff --git a/maps/rwlock_map.go b/maps/rwlock_map.go index 9091c19..a13635c 100644 --- a/maps/rwlock_map.go +++ b/maps/rwlock_map.go @@ -2,23 +2,21 @@ package maps import ( "sync" - - "golang.org/x/exp/constraints" ) var _ Map[string, any] = &rw_map[string, any]{} -type rw_map[K constraints.Ordered, V any] struct { +type rw_map[K hashable, V any] struct { m Map[K, V] mu sync.RWMutex } -func NewRWMap[K constraints.Ordered, V any](maps ...map[K]V) *rw_map[K, V] { +func NewRWMap[K hashable, V any](maps ...map[K]V) *rw_map[K, V] { merged := Merge(maps...) return &rw_map[K, V]{m: NewHashMap(merged)} } -func newRWMap[K constraints.Ordered, V any](m Map[K, V]) *rw_map[K, V] { +func newRWMap[K hashable, V any](m Map[K, V]) *rw_map[K, V] { return &rw_map[K, V]{m: m} } @@ -74,28 +72,13 @@ func (m *rw_map[K, V]) Count() int { return m.m.Count() } -func (m *rw_map[K, V]) Iter() <-chan *Entry[K, V] { - m.mu.RLock() - defer m.mu.RUnlock() +// func (m *rw_map[K, V]) Iter() <-chan *Entry[K, V] { +// m.mu.RLock() +// defer m.mu.RUnlock() - return m.m.Iter() -} +// return m.m.Iter() +// } func (m *rw_map[K, V]) ForEach(f func(K, V) bool) { - m.mu.RLock() - cloned := m.m.Clone() - m.mu.RUnlock() - - cloned.ForEach(f) -} - -func (m *rw_map[K, V]) Clone() Map[K, V] { - return newRWMap(m.m.Clone()) -} - -func (m *rw_map[K, V]) Clear() { - m.mu.Lock() - m.m.Clear() - m.mu.Unlock() } diff --git a/maps/sort_map.go b/maps/sort_map.go index e0cc8d4..0bd3b74 100644 --- a/maps/sort_map.go +++ b/maps/sort_map.go @@ -3,29 +3,27 @@ package maps import ( "fmt" - "golang.org/x/exp/constraints" "golang.org/x/exp/slices" xmaps "golang.org/x/exp/maps" ) var ( - _ Map[string, any] = &sorted_map[string, any]{} _ SortedMap[string, any] = &sorted_map[string, any]{} ) -type SortedMap[K constraints.Ordered, V any] interface { +type SortedMap[K hashable, V any] interface { Map[K, V] Asc() SortedMap[K, V] Desc() SortedMap[K, V] } -type sorted_map[K constraints.Ordered, V any] struct { +type sorted_map[K hashable, V any] struct { keys []K maps Map[K, V] } -func NewSortedMap[K constraints.Ordered, V any](maps ...map[K]V) *sorted_map[K, V] { +func NewSortedMap[K hashable, V any](maps ...map[K]V) *sorted_map[K, V] { merged := Merge(maps...) return &sorted_map[K, V]{ keys: xmaps.Keys(merged), @@ -33,7 +31,7 @@ func NewSortedMap[K constraints.Ordered, V any](maps ...map[K]V) *sorted_map[K, } } -func NewSortedByMap[K constraints.Ordered, V any](m Map[K, V]) *sorted_map[K, V] { +func NewSortedByMap[K hashable, V any](m Map[K, V]) *sorted_map[K, V] { return &sorted_map[K, V]{maps: m, keys: m.Keys()} } @@ -43,6 +41,8 @@ func (m *sorted_map[K, V]) Get(key K) (V, bool) { func (m *sorted_map[K, V]) Set(key K, value V) { m.maps.Set(key, value) + + slices.Sort(m.keys) m.keys = append(m.keys, key) } @@ -61,15 +61,6 @@ func (m *sorted_map[K, V]) Count() int { return m.maps.Count() } -func (m *sorted_map[K, V]) Clear() { - m.keys = make([]K, 0) - m.maps.Clear() -} - -func (m *sorted_map[K, V]) Clone() Map[K, V] { - return &sorted_map[K, V]{maps: m.maps.Clone(), keys: m.Keys()} -} - func (m *sorted_map[K, V]) Iter() <-chan *Entry[K, V] { c := make(chan *Entry[K, V], m.Count()) go func() {