From 6d39dbb942b3d40faeb31cdfe9594299acfe54fd Mon Sep 17 00:00:00 2001 From: charlie <3140647@qq.com> Date: Tue, 31 May 2022 13:47:48 +0800 Subject: [PATCH] map --- maps/concurrence_test.go | 40 ++++++++++++++++++++++++++++++++++++++++ maps/concurrent_map.go | 14 +++++++++++--- maps/hash_map.go | 7 +++---- maps/hash_map_test.go | 4 +++- maps/map.go | 7 ++++--- maps/option.go | 2 +- maps/rwlock_map.go | 10 ++++++---- maps/sort_map.go | 6 ++++-- 8 files changed, 72 insertions(+), 18 deletions(-) diff --git a/maps/concurrence_test.go b/maps/concurrence_test.go index d71777e..25ad3ab 100644 --- a/maps/concurrence_test.go +++ b/maps/concurrence_test.go @@ -1,6 +1,7 @@ package maps import ( + "fmt" "sync" "testing" "time" @@ -25,3 +26,42 @@ func TestConcurrence(t *testing.T) { wg.Wait() } + +func TestConcurrenceMapForeach(t *testing.T) { + m := NewConcurrentMap[string, string]() + m.Set("a", "a") + + m.ForEach(func(s1, s2 string) bool { + fmt.Println(s1, s2) + return false + }) +} + +func BenchmarkItor(b *testing.B) { + m := NewHashMap[string, string]().Synchronize() + + b.RunParallel(func(p *testing.PB) { + for p.Next() { + m.Set("a", "b") + for entity := range m.Iter() { + m.Delete(entity.Key) + } + } + }) + +} + +func BenchmarkMap(b *testing.B) { + m := NewHashMap[string, string]().Synchronize() + + b.RunParallel(func(p *testing.PB) { + for p.Next() { + m.Set("a", "a") + + m.ForEach(func(s1, s2 string) bool { + m.Delete("a") + return false + }) + } + }) +} diff --git a/maps/concurrent_map.go b/maps/concurrent_map.go index 300b8ca..0ceab77 100644 --- a/maps/concurrent_map.go +++ b/maps/concurrent_map.go @@ -17,7 +17,7 @@ type concurrnetMap[K constraints.Ordered, V any] struct { numOfBuckets uint64 } -func NewConcurrentMap[K constraints.Ordered, V any]() *concurrnetMap[K, V] { +func NewConcurrentMap[K constraints.Ordered, V any](maps ...map[K]V) *concurrnetMap[K, V] { num := defaultNumOfBuckets buckets := make([]Map[K, V], num) @@ -25,10 +25,18 @@ func NewConcurrentMap[K constraints.Ordered, V any]() *concurrnetMap[K, V] { buckets[i] = NewRWMap[K, V]() } - return &concurrnetMap[K, V]{ + m := &concurrnetMap[K, V]{ numOfBuckets: uint64(num), buckets: buckets, } + + for k := range maps { + for k, v := range maps[k] { + m.Set(k, v) + } + } + + return m } func (m *concurrnetMap[K, V]) Set(key K, value V) { @@ -87,7 +95,7 @@ func (m *concurrnetMap[K, V]) ToMap() map[K]V { return mm } -func (m *concurrnetMap[K, V]) ForEach(f func(K, V)) { +func (m *concurrnetMap[K, V]) ForEach(f func(K, V) bool) { var wg sync.WaitGroup num := int(m.numOfBuckets) diff --git a/maps/hash_map.go b/maps/hash_map.go index 2425a24..79bcc81 100644 --- a/maps/hash_map.go +++ b/maps/hash_map.go @@ -74,11 +74,10 @@ func (m *hashMap[K, V]) Iter() <-chan *Entry[K, V] { return ch } -func (m *hashMap[K, V]) ForEach(f func(K, V)) { - m.opt.mu.RLock() - defer m.opt.mu.RUnlock() +func (m *hashMap[K, V]) ForEach(f func(K, V) bool ) { + cloned := m.ToMap() - for k, v := range m.m { + for k, v := range cloned { f(k, v) } } diff --git a/maps/hash_map_test.go b/maps/hash_map_test.go index 8497415..2a60c4a 100644 --- a/maps/hash_map_test.go +++ b/maps/hash_map_test.go @@ -13,10 +13,12 @@ func TestForEach(t *testing.T) { assert.True(t, hashMap.Exist("a")) assert.Equal(t, len(m), hashMap.Count()) - hashMap.ForEach(func(s string, a any) { + hashMap.ForEach(func(s string, a any) bool { if _, ok := m[s]; !ok { t.Fatal("值不存在") } + + return false }) for k := range m { diff --git a/maps/map.go b/maps/map.go index 77d51f4..b29b77a 100644 --- a/maps/map.go +++ b/maps/map.go @@ -17,8 +17,8 @@ type Map[K constraints.Ordered, V any] interface { Clone() Map[K, V] // 复制 Clear() // 清空 Count() int // 数量 - Iter() <-chan *Entry[K, V] - ForEach(f func(K, V)) + Iter() <-chan *Entry[K, V] // 迭代器 + ForEach(f func(K, V) bool) // ForEach } type Entry[K constraints.Ordered, V any] struct { @@ -41,8 +41,9 @@ 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 { slice := make([]string, 0, m.Count()) - m.ForEach(func(k K, v V) { + m.ForEach(func(k K, v V) bool { slice = append(slice, f(k, v)) + return false }) return strings.Join(slice, sep) diff --git a/maps/option.go b/maps/option.go index 58af67c..ab4b2ea 100644 --- a/maps/option.go +++ b/maps/option.go @@ -10,5 +10,5 @@ type options struct { } func acquireDefaultOptions() *options { - return &options{mu: locker.NewEmptyLocker()} + return &options{mu: locker.EmptyLocker} } diff --git a/maps/rwlock_map.go b/maps/rwlock_map.go index 3db203c..74d6f68 100644 --- a/maps/rwlock_map.go +++ b/maps/rwlock_map.go @@ -77,11 +77,13 @@ func (m *rw_map[K, V]) Iter() <-chan *Entry[K, V] { return m.m.Iter() } -func (m *rw_map[K, V]) ForEach(f func(K, V)) { - m.mu.RLock() - defer m.mu.RUnlock() +func (m *rw_map[K, V]) ForEach(f func(K, V) bool) { - m.m.ForEach(f) + m.mu.RLock() + cloned := m.m.Clone() + m.mu.RUnlock() + + cloned.ForEach(f) } func (m *rw_map[K, V]) Clone() Map[K, V] { diff --git a/maps/sort_map.go b/maps/sort_map.go index 7ddbb4d..8846c38 100644 --- a/maps/sort_map.go +++ b/maps/sort_map.go @@ -87,10 +87,12 @@ func (m *sorted_map[K, V]) Iter() <-chan *Entry[K, V] { return c } -func (m *sorted_map[K, V]) ForEach(f func(K, V)) { +func (m *sorted_map[K, V]) ForEach(f func(K, V) bool) { for _, k := range m.keys { if v, ok := m.Get(k); ok { - f(k, v) + if f(k, v) { + break + } } } }