1
0
mirror of https://github.com/charlienet/go-mixed.git synced 2025-07-18 08:32:40 +08:00
This commit is contained in:
2022-05-12 11:32:03 +08:00
parent 7930a64e59
commit 08309e4a49
7 changed files with 85 additions and 37 deletions

View File

@ -12,12 +12,12 @@ import (
var defaultNumOfBuckets = runtime.GOMAXPROCS(runtime.NumCPU()) var defaultNumOfBuckets = runtime.GOMAXPROCS(runtime.NumCPU())
type ConcurrnetMap[K constraints.Ordered, V any] struct { type concurrnetMap[K constraints.Ordered, V any] struct {
buckets []Map[K, V] buckets []Map[K, V]
numOfBuckets uint64 numOfBuckets uint64
} }
func NewConcurrentMap[K constraints.Ordered, V any]() *ConcurrnetMap[K, V] { func NewConcurrentMap[K constraints.Ordered, V any]() *concurrnetMap[K, V] {
num := defaultNumOfBuckets num := defaultNumOfBuckets
buckets := make([]Map[K, V], num) buckets := make([]Map[K, V], num)
@ -25,31 +25,31 @@ func NewConcurrentMap[K constraints.Ordered, V any]() *ConcurrnetMap[K, V] {
buckets[i] = NewRWMap[K, V]() buckets[i] = NewRWMap[K, V]()
} }
return &ConcurrnetMap[K, V]{ return &concurrnetMap[K, V]{
numOfBuckets: uint64(num), numOfBuckets: uint64(num),
buckets: buckets, buckets: buckets,
} }
} }
func (m *ConcurrnetMap[K, V]) Set(key K, value V) { func (m *concurrnetMap[K, V]) Set(key K, value V) {
m.getBucket(key).Set(key, value) m.getBucket(key).Set(key, value)
} }
func (m *ConcurrnetMap[K, V]) Get(key K) (V, bool) { func (m *concurrnetMap[K, V]) Get(key K) (V, bool) {
return m.getBucket(key).Get(key) return m.getBucket(key).Get(key)
} }
func (m *ConcurrnetMap[K, V]) Delete(key K) { func (m *concurrnetMap[K, V]) Delete(key K) {
im := m.getBucket(key) im := m.getBucket(key)
im.Delete(key) im.Delete(key)
} }
func (m *ConcurrnetMap[K, V]) Exist(key K) bool { func (m *concurrnetMap[K, V]) Exist(key K) bool {
mm := m.getBucket(key) mm := m.getBucket(key)
return mm.Exist(key) return mm.Exist(key)
} }
func (m *ConcurrnetMap[K, V]) Iter() <-chan *Entry[K, V] { func (m *concurrnetMap[K, V]) Iter() <-chan *Entry[K, V] {
num := int(m.numOfBuckets) num := int(m.numOfBuckets)
ch := make(chan *Entry[K, V], m.Count()) ch := make(chan *Entry[K, V], m.Count())
for i := 0; i < num; i++ { for i := 0; i < num; i++ {
@ -60,7 +60,7 @@ func (m *ConcurrnetMap[K, V]) Iter() <-chan *Entry[K, V] {
return ch return ch
} }
func (m *ConcurrnetMap[K, V]) Keys() []K { func (m *concurrnetMap[K, V]) Keys() []K {
keys := make([]K, m.Count()) keys := make([]K, m.Count())
for _, b := range m.buckets { for _, b := range m.buckets {
keys = append(keys, b.Keys()...) keys = append(keys, b.Keys()...)
@ -69,7 +69,7 @@ func (m *ConcurrnetMap[K, V]) Keys() []K {
return keys return keys
} }
func (m *ConcurrnetMap[K, V]) Values() []V { func (m *concurrnetMap[K, V]) Values() []V {
values := make([]V, 0, m.Count()) values := make([]V, 0, m.Count())
for _, v := range m.buckets { for _, v := range m.buckets {
values = append(values, v.Values()...) values = append(values, v.Values()...)
@ -78,7 +78,7 @@ func (m *ConcurrnetMap[K, V]) Values() []V {
return values return values
} }
func (m *ConcurrnetMap[K, V]) ToMap() map[K]V { func (m *concurrnetMap[K, V]) ToMap() map[K]V {
mm := make(map[K]V, m.Count()) mm := make(map[K]V, m.Count())
for _, v := range m.buckets { for _, v := range m.buckets {
mm = Merge(mm, v.ToMap()) mm = Merge(mm, v.ToMap())
@ -87,7 +87,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)) {
var wg sync.WaitGroup var wg sync.WaitGroup
num := int(m.numOfBuckets) num := int(m.numOfBuckets)
@ -103,7 +103,7 @@ func (m *ConcurrnetMap[K, V]) ForEach(f func(K, V)) {
wg.Wait() wg.Wait()
} }
func (m *ConcurrnetMap[K, V]) Clone() Map[K, V] { func (m *concurrnetMap[K, V]) Clone() Map[K, V] {
num := int(m.numOfBuckets) num := int(m.numOfBuckets)
@ -112,19 +112,19 @@ func (m *ConcurrnetMap[K, V]) Clone() Map[K, V] {
buckets[i] = m.buckets[i].Clone() buckets[i] = m.buckets[i].Clone()
} }
return &ConcurrnetMap[K, V]{ return &concurrnetMap[K, V]{
buckets: buckets, buckets: buckets,
numOfBuckets: m.numOfBuckets, numOfBuckets: m.numOfBuckets,
} }
} }
func (m *ConcurrnetMap[K, V]) Clear() { func (m *concurrnetMap[K, V]) Clear() {
for i := 0; i < int(m.numOfBuckets); i++ { for i := 0; i < int(m.numOfBuckets); i++ {
m.buckets[i].Clear() m.buckets[i].Clear()
} }
} }
func (m *ConcurrnetMap[K, V]) Count() int { func (m *concurrnetMap[K, V]) Count() int {
var count int var count int
for i := 0; i < int(m.numOfBuckets); i++ { for i := 0; i < int(m.numOfBuckets); i++ {
count += m.buckets[i].Count() count += m.buckets[i].Count()
@ -133,7 +133,7 @@ func (m *ConcurrnetMap[K, V]) Count() int {
return count return count
} }
func (m *ConcurrnetMap[K, V]) getBucket(k K) Map[K, V] { func (m *concurrnetMap[K, V]) getBucket(k K) Map[K, V] {
id := getTag(k) % m.numOfBuckets id := getTag(k) % m.numOfBuckets
return m.buckets[id] return m.buckets[id]
} }

View File

@ -9,7 +9,12 @@ type hashMap[K constraints.Ordered, V any] struct {
} }
func NewHashMap[K constraints.Ordered, V any](maps ...map[K]V) *hashMap[K, V] { func NewHashMap[K constraints.Ordered, V any](maps ...map[K]V) *hashMap[K, V] {
return &hashMap[K, V]{m: make(map[K]V)} m := make(map[K]V)
if len(maps) > 0 {
m = Merge(maps...)
}
return &hashMap[K, V]{m: m}
} }
// synchronized // synchronized

25
maps/hash_map_test.go Normal file
View File

@ -0,0 +1,25 @@
package maps
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestForEach(t *testing.T) {
m := map[string]any{"b": "b", "a": "a", "d": "d", "c": "c"}
var hashMap = NewHashMap(map[string]any{"b": "b", "a": "a", "d": "d", "c": "c"})
assert.True(t, hashMap.Exist("a"))
assert.Equal(t, len(m), hashMap.Count())
hashMap.ForEach(func(s string, a any) {
if _, ok := m[s]; !ok {
t.Fatal("值不存在")
}
})
for k := range m {
assert.True(t, hashMap.Exist(k))
}
}

15
maps/option.go Normal file
View File

@ -0,0 +1,15 @@
package maps
import (
"sync"
"github.com/charlienet/go-mixed/locker"
)
type options struct {
mu sync.Locker
}
func acquireDefaultOptions() *options {
return &options{mu: locker.NewEmptyLocker()}
}

View File

@ -36,8 +36,8 @@ func (m *rw_map[K, V]) Get(key K) (V, bool) {
} }
func (m *rw_map[K, V]) Delete(key K) { func (m *rw_map[K, V]) Delete(key K) {
m.mu.RLock() m.mu.Lock()
defer m.mu.RUnlock() defer m.mu.Unlock()
m.m.Delete(key) m.m.Delete(key)
} }

View File

@ -5,6 +5,8 @@ import (
"golang.org/x/exp/constraints" "golang.org/x/exp/constraints"
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
xmaps "golang.org/x/exp/maps"
) )
var ( var (
@ -26,7 +28,7 @@ type sorted_map[K constraints.Ordered, V any] struct {
func NewSortedMap[K constraints.Ordered, V any](maps ...map[K]V) *sorted_map[K, V] { func NewSortedMap[K constraints.Ordered, V any](maps ...map[K]V) *sorted_map[K, V] {
merged := Merge(maps...) merged := Merge(maps...)
return &sorted_map[K, V]{ return &sorted_map[K, V]{
keys: keys(merged), keys: xmaps.Keys(merged),
maps: NewHashMap(merged), maps: NewHashMap(merged),
} }
} }
@ -115,12 +117,6 @@ func (s *sorted_map[K, V]) ToMap() map[K]V {
return s.maps.ToMap() return s.maps.ToMap()
} }
func (m *sorted_map[K, V]) String() string {
return fmt.Sprintf("map[%s]", Join[K, V](m, " ", func(k K, v V) string {
return fmt.Sprintf("%v:%v", k, v)
}))
}
func (m *sorted_map[K, V]) Asc() SortedMap[K, V] { func (m *sorted_map[K, V]) Asc() SortedMap[K, V] {
keys := m.keys keys := m.keys
slices.Sort(keys) slices.Sort(keys)
@ -144,11 +140,8 @@ func (m *sorted_map[K, V]) Desc() SortedMap[K, V] {
} }
} }
func keys[K comparable, V any](m map[K]V) []K { func (m *sorted_map[K, V]) String() string {
keys := make([]K, 0, len(m)) return fmt.Sprintf("map[%s]", Join[K, V](m, " ", func(k K, v V) string {
for k := range m { return fmt.Sprintf("%v:%v", k, v)
keys = append(keys, k) }))
}
return keys
} }

View File

@ -3,6 +3,8 @@ package maps
import ( import (
"fmt" "fmt"
"testing" "testing"
"github.com/stretchr/testify/assert"
) )
func TestSortMapConvert(t *testing.T) { func TestSortMapConvert(t *testing.T) {
@ -16,9 +18,17 @@ func TestSortMapConvert(t *testing.T) {
} }
func TestSortedJoin(t *testing.T) { func TestSortedJoin(t *testing.T) {
var m = NewSortedMap(map[string]any{"b": "b", "a": "a", "d": "d", "c": "c"}).Asc() m := NewSortedMap(map[string]any{"b": "b", "a": "a", "d": "d", "c": "c"}).Asc()
t.Log(Join[string, any](m, "&", func(k string, v any) string { f := func(k string, v any) string {
return fmt.Sprintf("%s=%v", k, v) return fmt.Sprintf("%s=%v", k, v)
})) }
ret := Join[string, any](m, "&", f)
assert.Equal(t, ret, "a=a&b=b&c=c&d=d")
ret = Join[string, any](m.Desc(), "&", f)
assert.Equal(t, "d=d&c=c&b=b&a=a", ret)
} }