Skip to content

Commit c600f3a

Browse files
LanceAddCopilot
andauthored
feat(container): Add NewXXXWithChecker function for gmap/gset/gtree (gogf#4610)
为了解决开发者需要通过`var`在代码顶部创建`gmap/gset/gtree`时需要同时设置`nilchecker`的需求,为这几个容易增加带有`checker`入参的构造函数`NewxxxxWithChecker`和`NewxxxWithCheckerFrom` --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 9dd43cd commit c600f3a

10 files changed

Lines changed: 299 additions & 4 deletions

container/gmap/gmap_hash_k_v_map.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,18 @@ type KVMap[K comparable, V any] struct {
2828
}
2929

3030
// NewKVMap creates and returns an empty hash map.
31-
// The parameter `safe` is used to specify whether to use the map in concurrent-safety mode,
32-
// which is false by default.
31+
// The parameter `safe` is used to specify whether to use the map in concurrent-safety mode, which is false by default.
3332
func NewKVMap[K comparable, V any](safe ...bool) *KVMap[K, V] {
3433
return NewKVMapFrom(make(map[K]V), safe...)
3534
}
3635

36+
// NewKVMapWithChecker creates and returns an empty hash map with a custom nil checker.
37+
// The parameter `checker` is a function used to determine if a value is nil.
38+
// The parameter `safe` is used to specify whether to use the map in concurrent-safety mode, which is false by default.
39+
func NewKVMapWithChecker[K comparable, V any](checker NilChecker[V], safe ...bool) *KVMap[K, V] {
40+
return NewKVMapWithCheckerFrom(make(map[K]V), checker, safe...)
41+
}
42+
3743
// NewKVMapFrom creates and returns a hash map from given map `data`.
3844
// Note that, the param `data` map will be set as the underlying data map (no deep copy),
3945
// there might be some concurrent-safe issues when changing the map outside.
@@ -45,6 +51,17 @@ func NewKVMapFrom[K comparable, V any](data map[K]V, safe ...bool) *KVMap[K, V]
4551
return m
4652
}
4753

54+
// NewKVMapWithCheckerFrom creates and returns a hash map from given map `data` with a custom nil checker.
55+
// Note that, the param `data` map will be set as the underlying data map (no deep copy),
56+
// and there might be some concurrent-safe issues when changing the map outside.
57+
// The parameter `checker` is a function used to determine if a value is nil.
58+
// The parameter `safe` is used to specify whether to use the map in concurrent-safety mode, which is false by default.
59+
func NewKVMapWithCheckerFrom[K comparable, V any](data map[K]V, checker NilChecker[V], safe ...bool) *KVMap[K, V] {
60+
m := NewKVMapFrom[K, V](data, safe...)
61+
m.RegisterNilChecker(checker)
62+
return m
63+
}
64+
4865
// RegisterNilChecker registers a custom nil checker function for the map values.
4966
// This function is used to determine if a value should be considered as nil.
5067
// The nil checker function takes a value of type V and returns a boolean indicating

container/gmap/gmap_list_k_v_map.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@ func NewListKVMap[K comparable, V any](safe ...bool) *ListKVMap[K, V] {
5050
}
5151
}
5252

53+
// NewListKVMapWithChecker creates and returns a new ListKVMap instance with a custom nil checker.
54+
// The parameter `checker` is a function used to determine if a value is nil.
55+
// The parameter `safe` is used to specify whether using map in concurrent-safety,
56+
// which is false by default.
57+
func NewListKVMapWithChecker[K comparable, V any](checker NilChecker[V], safe ...bool) *ListKVMap[K, V] {
58+
m := NewListKVMap[K, V](safe...)
59+
m.RegisterNilChecker(checker)
60+
return m
61+
}
62+
5363
// NewListKVMapFrom returns a link map from given map `data`.
5464
// Note that, the param `data` map will be copied to the underlying data structure,
5565
// so changes to the original map will not affect the link map.
@@ -59,6 +69,18 @@ func NewListKVMapFrom[K comparable, V any](data map[K]V, safe ...bool) *ListKVMa
5969
return m
6070
}
6171

72+
// NewListKVMapWithCheckerFrom returns a link map from given map `data` with a custom nil checker.
73+
// Note that, the param `data` map will be copied to the underlying data structure,
74+
// so changes to the original map will not affect the link map.
75+
// The parameter `checker` is a function used to determine if a value is nil.
76+
// The parameter `safe` is used to specify whether using map in concurrent-safety,
77+
// which is false by default.
78+
func NewListKVMapWithCheckerFrom[K comparable, V any](data map[K]V, nilChecker NilChecker[V], safe ...bool) *ListKVMap[K, V] {
79+
m := NewListKVMapWithChecker[K, V](nilChecker, safe...)
80+
m.Sets(data)
81+
return m
82+
}
83+
6284
// RegisterNilChecker registers a custom nil checker function for the map values.
6385
// This function is used to determine if a value should be considered as nil.
6486
// The nil checker function takes a value of type V and returns a boolean indicating

container/gmap/gmap_z_unit_k_v_map_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1663,3 +1663,34 @@ func Test_KVMap_TypedNil(t *testing.T) {
16631663
t.Assert(m2.Size(), 5)
16641664
})
16651665
}
1666+
1667+
func Test_NewKVMapWithChecker_TypedNil(t *testing.T) {
1668+
gtest.C(t, func(t *gtest.T) {
1669+
type Student struct {
1670+
Name string
1671+
Age int
1672+
}
1673+
m1 := gmap.NewKVMap[int, *Student](true)
1674+
for i := 0; i < 10; i++ {
1675+
m1.GetOrSetFuncLock(i, func() *Student {
1676+
if i%2 == 0 {
1677+
return &Student{}
1678+
}
1679+
return nil
1680+
})
1681+
}
1682+
t.Assert(m1.Size(), 10)
1683+
m2 := gmap.NewKVMapWithChecker[int, *Student](func(student *Student) bool {
1684+
return student == nil
1685+
}, true)
1686+
for i := 0; i < 10; i++ {
1687+
m2.GetOrSetFuncLock(i, func() *Student {
1688+
if i%2 == 0 {
1689+
return &Student{}
1690+
}
1691+
return nil
1692+
})
1693+
}
1694+
t.Assert(m2.Size(), 5)
1695+
})
1696+
}

container/gmap/gmap_z_unit_list_k_v_map_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,3 +1374,34 @@ func Test_ListKVMap_TypedNil(t *testing.T) {
13741374
t.Assert(m2.Size(), 5)
13751375
})
13761376
}
1377+
1378+
func Test_NewListKVMapWithChecker_TypedNil(t *testing.T) {
1379+
gtest.C(t, func(t *gtest.T) {
1380+
type Student struct {
1381+
Name string
1382+
Age int
1383+
}
1384+
m1 := gmap.NewListKVMap[int, *Student](true)
1385+
for i := 0; i < 10; i++ {
1386+
m1.GetOrSetFuncLock(i, func() *Student {
1387+
if i%2 == 0 {
1388+
return &Student{}
1389+
}
1390+
return nil
1391+
})
1392+
}
1393+
t.Assert(m1.Size(), 10)
1394+
m2 := gmap.NewListKVMapWithChecker[int, *Student](func(student *Student) bool {
1395+
return student == nil
1396+
}, true)
1397+
for i := 0; i < 10; i++ {
1398+
m2.GetOrSetFuncLock(i, func() *Student {
1399+
if i%2 == 0 {
1400+
return &Student{}
1401+
}
1402+
return nil
1403+
})
1404+
}
1405+
t.Assert(m2.Size(), 5)
1406+
})
1407+
}

container/gset/gset_t_set.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@ func NewTSet[T comparable](safe ...bool) *TSet[T] {
3434
}
3535
}
3636

37+
// NewTSetWithChecker creates and returns a new set with a custom nil checker.
38+
// The parameter `nilChecker` is a function used to determine if a value is nil.
39+
// The parameter `safe` is used to specify whether using set in concurrent-safety mode.
40+
func NewTSetWithChecker[T comparable](checker NilChecker[T], safe ...bool) *TSet[T] {
41+
s := NewTSet[T](safe...)
42+
s.RegisterNilChecker(checker)
43+
return s
44+
}
45+
3746
// NewTSetFrom returns a new set from `items`.
3847
// `items` - A slice of type T.
3948
func NewTSetFrom[T comparable](items []T, safe ...bool) *TSet[T] {
@@ -47,6 +56,16 @@ func NewTSetFrom[T comparable](items []T, safe ...bool) *TSet[T] {
4756
}
4857
}
4958

59+
// NewTSetWithCheckerFrom returns a new set from `items` with a custom nil checker.
60+
// The parameter `items` is a slice of elements to be added to the set.
61+
// The parameter `checker` is a function used to determine if a value is nil.
62+
// The parameter `safe` is used to specify whether using set in concurrent-safety mode.
63+
func NewTSetWithCheckerFrom[T comparable](items []T, checker NilChecker[T], safe ...bool) *TSet[T] {
64+
set := NewTSetWithChecker[T](checker, safe...)
65+
set.Add(items...)
66+
return set
67+
}
68+
5069
// RegisterNilChecker registers a custom nil checker function for the set elements.
5170
// This function is used to determine if an element should be considered as nil.
5271
// The nil checker function takes an element of type T and returns a boolean indicating
@@ -80,13 +99,13 @@ func (set *TSet[T]) Iterator(f func(v T) bool) {
8099
// Add adds one or multiple items to the set.
81100
func (set *TSet[T]) Add(items ...T) {
82101
set.mu.Lock()
102+
defer set.mu.Unlock()
83103
if set.data == nil {
84104
set.data = make(map[T]struct{})
85105
}
86106
for _, v := range items {
87107
set.data[v] = struct{}{}
88108
}
89-
set.mu.Unlock()
90109
}
91110

92111
// AddIfNotExist checks whether item exists in the set,

container/gset/gset_z_unit_t_set_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,3 +611,22 @@ func Test_TSet_TypedNil(t *testing.T) {
611611
t.Assert(exist2, false)
612612
})
613613
}
614+
615+
func Test_NewTSetWithChecker_TypedNil(t *testing.T) {
616+
gtest.C(t, func(t *gtest.T) {
617+
type Student struct {
618+
Name string
619+
Age int
620+
}
621+
set := gset.NewTSet[*Student](true)
622+
var s *Student = nil
623+
exist := set.AddIfNotExist(s)
624+
t.Assert(exist, true)
625+
626+
set2 := gset.NewTSetWithChecker[*Student](func(student *Student) bool {
627+
return student == nil
628+
}, true)
629+
exist2 := set2.AddIfNotExist(s)
630+
t.Assert(exist2, false)
631+
})
632+
}

container/gtree/gtree_k_v_avltree.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ func NewAVLKVTree[K comparable, V any](comparator func(v1, v2 K) int, safe ...bo
4747
}
4848
}
4949

50+
// NewAVLKVTreeWithChecker instantiates an AVL tree with the custom key comparator and nil checker.
51+
// The parameter `safe` is used to specify whether using tree in concurrent-safety, which is false in default.
52+
// The parameter `checker` is used to specify whether the given value is nil.
53+
func NewAVLKVTreeWithChecker[K comparable, V any](comparator func(v1, v2 K) int, checker NilChecker[V], safe ...bool) *AVLKVTree[K, V] {
54+
t := NewAVLKVTree[K, V](comparator, safe...)
55+
t.RegisterNilChecker(checker)
56+
return t
57+
}
58+
5059
// NewAVLKVTreeFrom instantiates an AVL tree with the custom key comparator and data map.
5160
//
5261
// The parameter `safe` is used to specify whether using tree in concurrent-safety, which is false in default.
@@ -58,6 +67,17 @@ func NewAVLKVTreeFrom[K comparable, V any](comparator func(v1, v2 K) int, data m
5867
return tree
5968
}
6069

70+
// NewAVLKVTreeWithCheckerFrom instantiates an AVL tree with the custom key comparator, nil checker and data map.
71+
// The parameter `safe` is used to specify whether using tree in concurrent-safety, which is false in default.
72+
// The parameter `checker` is used to specify whether the given value is nil.
73+
func NewAVLKVTreeWithCheckerFrom[K comparable, V any](comparator func(v1, v2 K) int, data map[K]V, checker NilChecker[V], safe ...bool) *AVLKVTree[K, V] {
74+
tree := NewAVLKVTreeWithChecker[K, V](comparator, checker, safe...)
75+
for k, v := range data {
76+
tree.doSet(k, v)
77+
}
78+
return tree
79+
}
80+
6181
// RegisterNilChecker registers a custom nil checker function for the map values.
6282
// This function is used to determine if a value should be considered as nil.
6383
// The nil checker function takes a value of type V and returns a boolean indicating

container/gtree/gtree_k_v_btree.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ func NewBKVTree[K comparable, V any](m int, comparator func(v1, v2 K) int, safe
4646
}
4747
}
4848

49+
// NewBKVTreeWithChecker instantiates a B-tree with `m` (maximum number of children), a custom key comparator and nil checker.
50+
// The parameter `safe` is used to specify whether using tree in concurrent-safety, which is false in default.
51+
// The parameter `checker` is used to specify whether the given value is nil.
52+
func NewBKVTreeWithChecker[K comparable, V any](m int, comparator func(v1, v2 K) int, checker NilChecker[V], safe ...bool) *BKVTree[K, V] {
53+
t := NewBKVTree[K, V](m, comparator, safe...)
54+
t.RegisterNilChecker(checker)
55+
return t
56+
}
57+
4958
// NewBKVTreeFrom instantiates a B-tree with `m` (maximum number of children), a custom key comparator and data map.
5059
// The parameter `safe` is used to specify whether using tree in concurrent-safety,
5160
// which is false in default.
@@ -57,6 +66,17 @@ func NewBKVTreeFrom[K comparable, V any](m int, comparator func(v1, v2 K) int, d
5766
return tree
5867
}
5968

69+
// NewBKVTreeWithCheckerFrom instantiates a B-tree with `m` (maximum number of children), a custom key comparator, nil checker and data map.
70+
// The parameter `safe` is used to specify whether using tree in concurrent-safety, which is false in default.
71+
// The parameter `checker` is used to specify whether the given value is nil.
72+
func NewBKVTreeWithCheckerFrom[K comparable, V any](m int, comparator func(v1, v2 K) int, data map[K]V, checker NilChecker[V], safe ...bool) *BKVTree[K, V] {
73+
tree := NewBKVTreeWithChecker[K, V](m, comparator, checker, safe...)
74+
for k, v := range data {
75+
tree.doSet(k, v)
76+
}
77+
return tree
78+
}
79+
6080
// RegisterNilChecker registers a custom nil checker function for the map values.
6181
// This function is used to determine if a value should be considered as nil.
6282
// The nil checker function takes a value of type V and returns a boolean indicating

container/gtree/gtree_k_v_redblacktree.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ func NewRedBlackKVTree[K comparable, V any](comparator func(v1, v2 K) int, safe
4242
return &tree
4343
}
4444

45+
// NewRedBlackKVTreeWithChecker instantiates a red-black tree with the custom key comparator and `nilChecker`.
46+
// The parameter `safe` is used to specify whether using tree in concurrent-safety, which is false in default.
47+
// The parameter `checker` is used to specify whether the given value is nil.
48+
func NewRedBlackKVTreeWithChecker[K comparable, V any](comparator func(v1, v2 K) int, checker NilChecker[V], safe ...bool) *RedBlackKVTree[K, V] {
49+
t := NewRedBlackKVTree[K, V](comparator, safe...)
50+
t.RegisterNilChecker(checker)
51+
return t
52+
}
53+
4554
// NewRedBlackKVTreeFrom instantiates a red-black tree with the custom key comparator and `data` map.
4655
// The parameter `safe` is used to specify whether using tree in concurrent-safety,
4756
// which is false in default.
@@ -51,6 +60,17 @@ func NewRedBlackKVTreeFrom[K comparable, V any](comparator func(v1, v2 K) int, d
5160
return &tree
5261
}
5362

63+
// NewRedBlackKVTreeWithCheckerFrom instantiates a red-black tree with the custom key comparator, `data` map and `nilChecker`.
64+
// The parameter `safe` is used to specify whether using tree in concurrent-safety, which is false in default.
65+
// The parameter `checker` is used to specify whether the given value is nil.
66+
func NewRedBlackKVTreeWithCheckerFrom[K comparable, V any](comparator func(v1, v2 K) int, data map[K]V, checker NilChecker[V], safe ...bool) *RedBlackKVTree[K, V] {
67+
t := NewRedBlackKVTreeWithChecker[K, V](comparator, checker, safe...)
68+
for k, v := range data {
69+
t.doSet(k, v)
70+
}
71+
return t
72+
}
73+
5474
// RedBlackKVTreeInit instantiates a red-black tree with the custom key comparator.
5575
// The parameter `safe` is used to specify whether using tree in concurrent-safety,
5676
// which is false in default.
@@ -210,7 +230,7 @@ func (tree *RedBlackKVTree[K, V]) GetOrSetFunc(key K, f func() V) V {
210230
// GetOrSetFuncLock returns its `value` of `key`, or sets value with returned value of callback function `f` if it does
211231
// not exist and then returns this value.
212232
//
213-
// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function `f`within mutex lock.
233+
// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function `f` within mutex lock.
214234
func (tree *RedBlackKVTree[K, V]) GetOrSetFuncLock(key K, f func() V) V {
215235
tree.mu.Lock()
216236
defer tree.mu.Unlock()

0 commit comments

Comments
 (0)