mirror of
https://github.com/charlienet/go-mixed.git
synced 2025-07-18 08:32:40 +08:00
fix err
This commit is contained in:
@ -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]
|
||||||
}
|
}
|
||||||
|
@ -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
25
maps/hash_map_test.go
Normal 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
15
maps/option.go
Normal 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()}
|
||||||
|
}
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user