From 5f9203404b9a01c46a5516c9d35f410bacf5bc6a Mon Sep 17 00:00:00 2001 From: charlie <3140647@qq.com> Date: Wed, 4 May 2022 23:46:07 +0800 Subject: [PATCH] oops --- collections/generics/array.go | 35 ---- collections/generics/array_test.go | 12 -- collections/generics/arraystack.go | 57 ------- collections/generics/concurrent_map.go | 127 --------------- collections/generics/concurrent_map_test.go | 168 -------------------- collections/generics/hashset.go | 73 --------- collections/generics/hashset_test.go | 24 --- collections/generics/map.go | 11 -- collections/generics/map_test.go | 59 ------- collections/generics/rwlock_map.go | 61 ------- collections/generics/sort_map.go | 107 ------------- collections/generics/sort_map_test.go | 45 ------ 12 files changed, 779 deletions(-) delete mode 100644 collections/generics/array.go delete mode 100644 collections/generics/array_test.go delete mode 100644 collections/generics/arraystack.go delete mode 100644 collections/generics/concurrent_map.go delete mode 100644 collections/generics/concurrent_map_test.go delete mode 100644 collections/generics/hashset.go delete mode 100644 collections/generics/hashset_test.go delete mode 100644 collections/generics/map.go delete mode 100644 collections/generics/map_test.go delete mode 100644 collections/generics/rwlock_map.go delete mode 100644 collections/generics/sort_map.go delete mode 100644 collections/generics/sort_map_test.go diff --git a/collections/generics/array.go b/collections/generics/array.go deleted file mode 100644 index a8d61b7..0000000 --- a/collections/generics/array.go +++ /dev/null @@ -1,35 +0,0 @@ -package generics - -type Array[T comparable] struct { - data []T - length int -} - -func NewArray[T comparable](values ...T) *Array[T] { - return &Array[T]{data: values, length: len(values)} -} - -func (a *Array[T]) Distinct(keepSorted bool) *Array[T] { - set := NewHashSet(a.data...) - if set.Size() == a.length { - return a - } - - if !keepSorted { - return NewArray(set.Values()...) - } - - ret := make([]T, 0, len(set)) - for _, v := range a.data { - if set.Contain(v) { - ret = append(ret, v) - set.Remove(v) - } - } - - return NewArray(ret...) -} - -func (a *Array[T]) ToList() []T { - return a.data -} diff --git a/collections/generics/array_test.go b/collections/generics/array_test.go deleted file mode 100644 index c74addb..0000000 --- a/collections/generics/array_test.go +++ /dev/null @@ -1,12 +0,0 @@ -package generics - -import "testing" - -func TestArray(t *testing.T) { - a := NewArray(9, 1, 2, 4, 3, 1, 3) - t.Log(a) - - b := a.Distinct(true) - t.Log(b) - t.Log(b.ToList()) -} diff --git a/collections/generics/arraystack.go b/collections/generics/arraystack.go deleted file mode 100644 index a4362f6..0000000 --- a/collections/generics/arraystack.go +++ /dev/null @@ -1,57 +0,0 @@ -package generics - -import "errors" - -type ArrayStack[T any] struct { - data []T - length int -} - -func NewArrayStack[T any]() *ArrayStack[T] { - return &ArrayStack[T]{data: []T{}, length: 0} -} - -func (s *ArrayStack[T]) Data() []T { - return s.data -} - -func (s *ArrayStack[T]) Size() int { - return s.length -} - -func (s *ArrayStack[T]) IsEmpty() bool { - return s.length == 0 -} - -// Push element into stack -func (s *ArrayStack[T]) Push(value T) { - s.data = append([]T{value}, s.data...) - s.length++ -} - -// Pop delete the top element of stack then return it, if stack is empty, return nil and error -func (s *ArrayStack[T]) Pop() (*T, error) { - if s.IsEmpty() { - return nil, errors.New("stack is empty") - } - - topItem := s.data[0] - s.data = s.data[1:] - s.length-- - - return &topItem, nil -} - -// Peak return the top element of stack then return it -func (s *ArrayStack[T]) Peak() (*T, error) { - if s.IsEmpty() { - return nil, errors.New("stack is empty") - } - return &s.data[0], nil -} - -// Clear the stack data -func (s *ArrayStack[T]) Clear() { - s.data = []T{} - s.length = 0 -} diff --git a/collections/generics/concurrent_map.go b/collections/generics/concurrent_map.go deleted file mode 100644 index 5c47b8b..0000000 --- a/collections/generics/concurrent_map.go +++ /dev/null @@ -1,127 +0,0 @@ -package generics - -import ( - "fmt" - "runtime" - "sync" - - "github.com/charlienet/go-mixed/bytesconv" - "github.com/charlienet/go-mixed/hash" -) - -var _ Map[string, string] = &ConcurrnetMap[string, string]{} - -var defaultNumOfBuckets = runtime.GOMAXPROCS(runtime.NumCPU()) - -type ConcurrnetMap[K comparable, V any] struct { - buckets []Map[K, V] - numOfBuckets uint64 -} - -func NewConcurrnetMap[K comparable, V any]() Map[K, V] { - num := defaultNumOfBuckets - - buckets := make([]Map[K, V], num) - for i := 0; i < num; i++ { - buckets[i] = NewRWLockMap[K, V]() - } - - return &ConcurrnetMap[K, V]{ - numOfBuckets: uint64(num), - buckets: buckets, - } -} - -func (m *ConcurrnetMap[K, V]) Set(key K, value V) { - m.getBucket(key).Set(key, value) -} - -func (m *ConcurrnetMap[K, V]) Get(key K) (V, bool) { - return m.getBucket(key).Get(key) -} - -func (m *ConcurrnetMap[K, V]) Delete(key K) { - im := m.getBucket(key) - im.Delete(key) -} - -func (m *ConcurrnetMap[K, V]) ForEach(f func(K, V)) { - var wg sync.WaitGroup - - num := int(m.numOfBuckets) - - wg.Add(int(m.numOfBuckets)) - for i := 0; i < num; i++ { - go func(i int) { - m.buckets[i].ForEach(f) - wg.Done() - }(i) - } - - wg.Wait() -} - -func (m *ConcurrnetMap[K, V]) Clone() Map[K, V] { - - num := int(m.numOfBuckets) - - buckets := make([]Map[K, V], m.numOfBuckets) - for i := 0; i < num; i++ { - buckets[i] = m.buckets[i].Clone() - } - - return &ConcurrnetMap[K, V]{ - buckets: buckets, - numOfBuckets: m.numOfBuckets, - } -} - -func (m *ConcurrnetMap[K, V]) Clear() { - for i := 0; i < int(m.numOfBuckets); i++ { - m.buckets[i].Clear() - } -} - -func (m *ConcurrnetMap[K, V]) Count() int { - var count int - for i := 0; i < int(m.numOfBuckets); i++ { - count += m.buckets[i].Count() - } - - return count -} - -func (m *ConcurrnetMap[K, V]) getBucket(k K) Map[K, V] { - id := getTag(k) % m.numOfBuckets - return m.buckets[id] -} - -func getTag[T comparable](v T) uint64 { - var vv any = v - - switch vv.(type) { - case string: - return fnv(vv.(string)) - case int8: - return uint64(vv.(int8)) - case uint8: - return uint64(vv.(uint8)) - case int: - return uint64(vv.(int)) - case int32: - return uint64(vv.(int32)) - case uint32: - return uint64(vv.(uint32)) - case int64: - return uint64(vv.(int64)) - case uint64: - return vv.(uint64) - default: - return fnv(fmt.Sprintf("%v", v)) - } -} - -func fnv(k string) uint64 { - bytes := bytesconv.StringToBytes(k) - return uint64(hash.Funv32(bytes)) -} diff --git a/collections/generics/concurrent_map_test.go b/collections/generics/concurrent_map_test.go deleted file mode 100644 index b38c94f..0000000 --- a/collections/generics/concurrent_map_test.go +++ /dev/null @@ -1,168 +0,0 @@ -package generics_test - -import ( - "fmt" - "runtime" - "testing" - - "github.com/charlienet/go-mixed/bytesconv" - "github.com/charlienet/go-mixed/collections/generics" - "github.com/charlienet/go-mixed/hash" -) - -func TestConcurrentMap(t *testing.T) { - t.Log(runtime.GOMAXPROCS(runtime.NumCPU())) - - key := "aaabc" - value := "aabcd" - - m := generics.NewConcurrnetMap[string, string]() - m.Set(key, value) - v, ok := m.Get(key) - t.Log("v:", v, ok) - - m.Delete(key) - v, ok = m.Get(key) - t.Log("v:", v, ok) -} - -func TestForEach(t *testing.T) { - - m := generics.NewConcurrnetMap[string, string]() - for k := 0; k < 10; k++ { - key := fmt.Sprintf("abc-%d", k) - value := fmt.Sprintf("abc-%d", k) - m.Set(key, value) - } - - m.ForEach(func(s1, s2 string) { - t.Log(s1, s2) - }) - - t.Log("finish") -} - -func TestExist(t *testing.T) { - key := "abc" - value := "bcd" - - m := generics.NewConcurrnetMap[string, string]() - m.Set(key, value) - - keyv2 := "abc" - - t.Logf("%p %p", &key, &keyv2) - _, ok := m.Get(keyv2) - t.Log("ok", ok) -} - -func BenchmarkConcurrnetMap(b *testing.B) { - key := "abc" - value := "bcd" - - m := generics.NewConcurrnetMap[string, string]() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - m.Set(key, value) - m.Get(key) - m.Delete(key) - } - }) -} - -func BenchmarkRWLockMap(b *testing.B) { - key := "abc" - value := "bcd" - - m := generics.NewRWLockMap[string, string]() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - m.Set(key, value) - m.Get(key) - m.Delete(key) - } - }) -} - -func BenchmarkGetIndex(b *testing.B) { - - b.Run("字符串-Sprintf", func(b *testing.B) { - v := "abc" - for i := 0; i < b.N; i++ { - bytes := []byte(fmt.Sprintf("%v", v)) - hash.XXHashUint64(bytes) - } - }) - - b.Run("字符串", func(b *testing.B) { - v := "abc" - for i := 0; i < b.N; i++ { - getTag(v) - } - }) - - b.Run("数字", func(b *testing.B) { - v := 124 - for i := 0; i < b.N; i++ { - getTag(v) - } - }) -} - -func getTag[T comparable](v T) uint64 { - var vv any = v - - switch vv.(type) { - case string: - return getStringIndex([]byte(vv.(string))) - case int8: - return uint64(vv.(int8)) - case uint8: - return uint64(vv.(uint8)) - case int: - return uint64(vv.(int)) - case int32: - return uint64(vv.(int32)) - case uint32: - return uint64(vv.(uint32)) - case int64: - return uint64(vv.(int64)) - case uint64: - return vv.(uint64) - default: - return getStringIndex([]byte(fmt.Sprintf("%v", v))) - } -} - -func getStringIndex(v []byte) uint64 { - if len(v) > 4 { - v = v[:4] - } - - // return hash.XXHashUint64(v) - i, _ := bytesconv.BigEndian.BytesToUInt64(v) - return i -} - -func TestFnv64(t *testing.T) { - t.Log(fnv64("a")) - t.Log(fnv64("b")) - t.Log(fnv64("c")) - t.Log(fnv64("d")) - t.Log(fnv64("e")) -} - -const ( - prime32 = uint64(16777619) -) - -func fnv64(k string) uint64 { - var hash = uint64(2166136261) - l := len(k) - for i := 0; i < l; i++ { - hash *= prime32 - hash ^= uint64(k[i]) - } - - return hash -} diff --git a/collections/generics/hashset.go b/collections/generics/hashset.go deleted file mode 100644 index 6b47f55..0000000 --- a/collections/generics/hashset.go +++ /dev/null @@ -1,73 +0,0 @@ -package generics - - -type Set[T comparable] map[T]struct{} - -func NewHashSet[T comparable](values ...T) Set[T] { - set := make(Set[T], len(values)) - set.Add(values...) - return set -} - -func (s Set[T]) Add(values ...T) { - for _, v := range values { - s[v] = struct{}{} - } -} - -func (s Set[T]) Remove(v T) { - delete(s, v) -} - -func (s Set[T]) Contain(value T) bool { - _, ok := s[value] - return ok -} - -func (s Set[T]) Clone() Set[T] { - set := NewHashSet[T]() - set.Add(s.Values()...) - return set -} - -func (s Set[T]) Iterate(fn func(value T)) { - for v := range s { - fn(v) - } -} - -// Union creates a new set contain all element of set s and other -func (s Set[T]) Union(other Set[T]) Set[T] { - set := s.Clone() - set.Add(other.Values()...) - return set -} - -// Intersection creates a new set whose element both be contained in set s and other -func (s Set[T]) Intersection(other Set[T]) Set[T] { - set := NewHashSet[T]() - s.Iterate(func(value T) { - if other.Contain(value) { - set.Add(value) - } - }) - - return set -} - -func (s Set[T]) Values() []T { - values := make([]T, 0, s.Size()) - s.Iterate(func(value T) { - values = append(values, value) - }) - - return values -} - -func (s Set[T]) IsEmpty() bool { - return len(s) == 0 -} - -func (s Set[T]) Size() int { - return len(s) -} diff --git a/collections/generics/hashset_test.go b/collections/generics/hashset_test.go deleted file mode 100644 index 774eb92..0000000 --- a/collections/generics/hashset_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package generics_test - -import ( - "testing" - - "github.com/charlienet/go-mixed/collections/generics" - "github.com/stretchr/testify/assert" -) - -func TestSet(t *testing.T) { - - s := generics.NewHashSet[int]() - s.Add(1, 2, 3) - - expected := generics.NewHashSet(1, 2, 3) - - _ = expected -} - -func TestSetExist(t *testing.T) { - s := generics.NewHashSet(1, 2, 3) - assert.True(t, s.Contain(1)) - assert.False(t, s.Contain(5)) -} diff --git a/collections/generics/map.go b/collections/generics/map.go deleted file mode 100644 index 01c72d3..0000000 --- a/collections/generics/map.go +++ /dev/null @@ -1,11 +0,0 @@ -package generics - -type Map[K comparable, V any] interface { - Set(key K, value V) - Get(key K) (V, bool) - Delete(key K) - ForEach(f func(K, V)) - Clone() Map[K, V] - Clear() - Count() int -} diff --git a/collections/generics/map_test.go b/collections/generics/map_test.go deleted file mode 100644 index 047ef81..0000000 --- a/collections/generics/map_test.go +++ /dev/null @@ -1,59 +0,0 @@ -package generics_test - -import ( - "testing" - - "github.com/charlienet/go-mixed/collections/generics" - "github.com/stretchr/testify/assert" -) - -func TestIMap(t *testing.T) { - k := "abc" - v := "bcd" - - var m generics.Map[string, string] = generics.NewConcurrnetMap[string, string]() - m.Set(k, v) - _, ok := m.Get(k) - assert.True(t, ok, "不存在") - t.Log(m.Count()) - - m.Delete(k) - _, ok = m.Get(k) - assert.False(t, ok, "不存在") - - t.Log(m.Count()) -} - -func TestMapCount(t *testing.T) { - mm := make(map[string]string) - mm["a"] = "b" - assert.Equal(t, 1, len(mm)) -} - -func BenchmarkMap(b *testing.B) { - b.Run("RWLock", func(b *testing.B) { - m := generics.NewRWLockMap[string, string]() - doBenchamark(b, m) - - }) - - b.Run("ConcurrnetMap", func(b *testing.B) { - doBenchamark(b, generics.NewConcurrnetMap[string, string]()) - }) -} - -func doBenchamark(b *testing.B, m generics.Map[string, string]) { - var k = "abc" - var v = "bcd" - - b.RunParallel(func(p *testing.PB) { - for p.Next() { - m.Set(k, v) - m.Get(k) - m.Get(k) - m.Get(k) - m.Delete(k) - } - }) - -} diff --git a/collections/generics/rwlock_map.go b/collections/generics/rwlock_map.go deleted file mode 100644 index cd7aaab..0000000 --- a/collections/generics/rwlock_map.go +++ /dev/null @@ -1,61 +0,0 @@ -package generics - -import ( - "sync" - - "golang.org/x/exp/maps" -) - -var _ Map[string, string] = &RWLockMap[string, string]{} - -type RWLockMap[K comparable, V any] struct { - m map[K]V - lock sync.RWMutex -} - -func NewRWLockMap[K comparable, V any]() Map[K, V] { - return &RWLockMap[K, V]{ - m: make(map[K]V), - } -} - -func (m *RWLockMap[K, V]) Get(key K) (V, bool) { - m.lock.RLock() - v, ok := m.m[key] - m.lock.RUnlock() - return v, ok -} - -func (m *RWLockMap[K, V]) Set(key K, value V) { - m.lock.Lock() - m.m[key] = value - m.lock.Unlock() -} - -func (m *RWLockMap[K, V]) Delete(key K) { - m.lock.Lock() - delete(m.m, key) - m.lock.Unlock() -} - -func (m *RWLockMap[K, V]) ForEach(f func(K, V)) { - for k, v := range m.m { - f(k, v) - } -} - -func (m *RWLockMap[K, V]) Clone() Map[K, V] { - new := maps.Clone(m.m) - - return &RWLockMap[K, V]{ - m: new, - } -} - -func (m *RWLockMap[K, V]) Clear() { - m.m = make(map[K]V) -} - -func (m *RWLockMap[K, V]) Count() int { - return len(m.m) -} diff --git a/collections/generics/sort_map.go b/collections/generics/sort_map.go deleted file mode 100644 index 60cf362..0000000 --- a/collections/generics/sort_map.go +++ /dev/null @@ -1,107 +0,0 @@ -package generics - -import ( - "fmt" - "strings" - - "golang.org/x/exp/constraints" - "golang.org/x/exp/slices" -) - -type mapSorter[K constraints.Ordered, V any] struct { - keys []K - m map[K]V -} - -func NewSortMap[K constraints.Ordered, V any](m map[K]V) *mapSorter[K, V] { - return &mapSorter[K, V]{ - m: m, - keys: keys(m), - } -} - -func (s *mapSorter[K, V]) Set(key K, value V) { - s.m[key] = value - s.keys = append(s.keys, key) -} - -func (s *mapSorter[K, V]) Get(key K) (V, bool) { - v, ok := s.m[key] - return v, ok -} - -func (s *mapSorter[K, V]) Delete(key K) { - delete(s.m, key) - - keys := keys(s.m) - s.keys = keys -} - -func (s *mapSorter[K, V]) Clear() { - s.m = map[K]V{} - s.keys = []K{} -} - -func (s *mapSorter[K, V]) Count() int { - return len(s.m) -} - -func (s *mapSorter[K, V]) Asc() *mapSorter[K, V] { - keys := s.keys - slices.Sort(keys) - - return &mapSorter[K, V]{ - m: s.m, - keys: keys, - } -} - -func (s *mapSorter[K, V]) Desc() *mapSorter[K, V] { - keys := s.keys - - slices.SortFunc(keys, func(a, b K) bool { - return a > b - }) - - return &mapSorter[K, V]{ - m: s.m, - keys: keys, - } -} - -func (s *mapSorter[K, V]) Join(sep string, f func(k K, v V) string) string { - slice := make([]string, 0, len(s.m)) - for _, k := range s.keys { - slice = append(slice, f(k, s.m[k])) - } - - return strings.Join(slice, sep) -} - -func (s *mapSorter[K, V]) Keys() []K { - return s.keys -} - -func (s *mapSorter[K, V]) Values() []V { - ret := make([]V, 0, len(s.m)) - for _, k := range s.keys { - ret = append(ret, s.m[k]) - } - - return ret -} - -func (s *mapSorter[K, V]) String() string { - return fmt.Sprintf("map[%s]", s.Join(" ", func(k K, v V) string { - return fmt.Sprintf("%v:%v", k, v) - })) -} - -func keys[K comparable, V any](m map[K]V) []K { - keys := make([]K, 0, len(m)) - for k := range m { - keys = append(keys, k) - } - - return keys -} diff --git a/collections/generics/sort_map_test.go b/collections/generics/sort_map_test.go deleted file mode 100644 index cbf84c7..0000000 --- a/collections/generics/sort_map_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package generics - -import ( - "fmt" - "testing" -) - -func TestSort(t *testing.T) { - m := map[string]any{ - "Bcd": "bcd", - "Abc": "abc", - } - - t.Log(NewSortMap(m).Values()) - t.Log(NewSortMap(m).Desc().Values()) - t.Log(NewSortMap(m).Asc().Values()) -} - -func TestMapSortInt(t *testing.T) { - m := map[string]int{ - "Bcd": 8, - "Abc": 4, - } - - ret := NewSortMap(m).Desc().Values() - t.Log(NewSortMap(m).Desc()) - t.Log(NewSortMap(m).Asc()) - - t.Log(ret) -} - -func TestJoin(t *testing.T) { - m := map[string]any{ - "Bcd": "bcd", - "Abc": "abc", - "Efg": "efg", - } - t.Log(m) - - j := NewSortMap(m).Asc().Join("&", func(k string, v any) string { - return fmt.Sprintf("%s=%v", k, v) - }) - - t.Log(j) -}