mirror of
https://github.com/charlienet/go-mixed.git
synced 2025-07-18 00:22:41 +08:00
map
This commit is contained in:
@ -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
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -10,5 +10,5 @@ type options struct {
|
||||
}
|
||||
|
||||
func acquireDefaultOptions() *options {
|
||||
return &options{mu: locker.NewEmptyLocker()}
|
||||
return &options{mu: locker.EmptyLocker}
|
||||
}
|
||||
|
@ -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] {
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user