1
0
mirror of https://github.com/charlienet/go-mixed.git synced 2025-07-18 00:22:41 +08:00
This commit is contained in:
2022-05-31 13:47:48 +08:00
parent ebf862e40b
commit 6d39dbb942
8 changed files with 72 additions and 18 deletions

View File

@ -1,6 +1,7 @@
package maps package maps
import ( import (
"fmt"
"sync" "sync"
"testing" "testing"
"time" "time"
@ -25,3 +26,42 @@ func TestConcurrence(t *testing.T) {
wg.Wait() 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
})
}
})
}

View File

@ -17,7 +17,7 @@ type concurrnetMap[K constraints.Ordered, V any] struct {
numOfBuckets uint64 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 num := defaultNumOfBuckets
buckets := make([]Map[K, V], num) 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]() buckets[i] = NewRWMap[K, V]()
} }
return &concurrnetMap[K, V]{ m := &concurrnetMap[K, V]{
numOfBuckets: uint64(num), numOfBuckets: uint64(num),
buckets: buckets, 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) { 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 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 var wg sync.WaitGroup
num := int(m.numOfBuckets) num := int(m.numOfBuckets)

View File

@ -74,11 +74,10 @@ func (m *hashMap[K, V]) Iter() <-chan *Entry[K, V] {
return ch return ch
} }
func (m *hashMap[K, V]) ForEach(f func(K, V)) { func (m *hashMap[K, V]) ForEach(f func(K, V) bool ) {
m.opt.mu.RLock() cloned := m.ToMap()
defer m.opt.mu.RUnlock()
for k, v := range m.m { for k, v := range cloned {
f(k, v) f(k, v)
} }
} }

View File

@ -13,10 +13,12 @@ func TestForEach(t *testing.T) {
assert.True(t, hashMap.Exist("a")) assert.True(t, hashMap.Exist("a"))
assert.Equal(t, len(m), hashMap.Count()) 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 { if _, ok := m[s]; !ok {
t.Fatal("值不存在") t.Fatal("值不存在")
} }
return false
}) })
for k := range m { for k := range m {

View File

@ -17,8 +17,8 @@ type Map[K constraints.Ordered, V any] interface {
Clone() Map[K, V] // 复制 Clone() Map[K, V] // 复制
Clear() // 清空 Clear() // 清空
Count() int // 数量 Count() int // 数量
Iter() <-chan *Entry[K, V] Iter() <-chan *Entry[K, V] // 迭代器
ForEach(f func(K, V)) ForEach(f func(K, V) bool) // ForEach
} }
type Entry[K constraints.Ordered, V any] struct { 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 { 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()) 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)) slice = append(slice, f(k, v))
return false
}) })
return strings.Join(slice, sep) return strings.Join(slice, sep)

View File

@ -10,5 +10,5 @@ type options struct {
} }
func acquireDefaultOptions() *options { func acquireDefaultOptions() *options {
return &options{mu: locker.NewEmptyLocker()} return &options{mu: locker.EmptyLocker}
} }

View File

@ -77,11 +77,13 @@ func (m *rw_map[K, V]) Iter() <-chan *Entry[K, V] {
return m.m.Iter() return m.m.Iter()
} }
func (m *rw_map[K, V]) ForEach(f func(K, V)) { func (m *rw_map[K, V]) ForEach(f func(K, V) bool) {
m.mu.RLock()
defer m.mu.RUnlock()
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] { func (m *rw_map[K, V]) Clone() Map[K, V] {

View File

@ -87,10 +87,12 @@ func (m *sorted_map[K, V]) Iter() <-chan *Entry[K, V] {
return c 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 { for _, k := range m.keys {
if v, ok := m.Get(k); ok { if v, ok := m.Get(k); ok {
f(k, v) if f(k, v) {
break
}
} }
} }
} }